代码随想录:栈与队列4-6

20.有效的括号

题目

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

代码

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        
        for(int i=0; i < s.length(); i++){
            char c = s.charAt(i);
            //如果是左括号,就让对应匹配的右括号进栈
            if(c == '('){
                stack.push(')');
            }
            else if(c == '{'){
                stack.push('}');
            }
            else if(c == '['){
                stack.push(']');
            }
            //如果是右括号,如果此时栈已经空了,说明右括号多了,返回false
            //如果是右括号,如果左右括号不匹配,返回false
            else if(stack.isEmpty() || c != stack.peek()){
                return false;
            }
            //左右括号匹配,栈顶元素出栈
            else{
                stack.pop();
            }
        }
        //如果结束后栈非空,说明左括号多了,也要return false
        return stack.isEmpty();
    }
}

总结

1.思想

        要判断左右括号匹配,优先用栈来解决。

        大致算法是,如果是左括号就让其进栈,如果是右括号就把栈顶元素取出来匹配一下,如果不匹配就返回false,匹配就把栈底元素出栈。不过要把所有不匹配的情况考虑清楚:

(1)第一种:左括号多,那么for循环结束之后的栈是非空的

(2)第二种:右括号多,那么遍历到右括号时栈已经是空了

(3)第三种就:左右括号数量匹配但是内容不匹配。

        还有要想一下,如何做左右括号的匹配,其实就是让左括号进栈的时候,替换为对应的右括号就行。

2.算法流程

        用for循环遍历字符串,如果当前元素是左括号“(、{、[ ”,就分别使用三个if分支语句,让其对应的右括号“)、}、] ”进栈。

        如果当前元素已经不是上面3种左括号,已经是右括号了,要判断2种情况,如果此时的栈已经是空的,就代表右括号太多,要返回false,或者如果此时的左右括号不匹配,也要返回false。如果上面的情况都不满足,说明左右括号是匹配的,把栈顶元素pop出来。

        最后,判断栈是否为空,看看左括号是不是太多了就行。

1047.删除字符串中的所有相邻重复项

题目

        给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:

输入:"abbaca"
输出:"ca"

代码

class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();

        for(int i=0;i < s.length(); i++){
            char c = s.charAt(i);
            //如果栈是空的,或者栈不空但是栈顶元素!=当前元素
            if(stack.isEmpty() || stack.peek() != c){
                stack.push(c); //当前元素入栈
            }
            //如果栈非空,且栈顶元素==当前元素
            else{
                stack.pop(); //栈顶元素出栈
            }
        }

        StringBuilder sb = new StringBuilder();
        //把最终的栈元素从栈顶开始输出
        while(!stack.isEmpty()){
            sb.append(stack.pop());
        }

        //出栈顺序和我们要的结果相反,要把结果字符串反转一下再转为String类型
        return sb.reverse().toString();

    }
}

总结

1.思想

        字符串删除重复元素也是一种变相的括号匹配问题。核心思路如下:

        如果栈是空的或者栈顶元素和当前元素不相同,就把当前元素入栈。

        如果栈顶元素等于当前元素,就把栈顶出栈。最后遍历完String后,栈内剩余的就是我们要的不重复的字符串。

2.算法流程

        for循环遍历字符串,获取当前元素c,如果当前栈是空或者栈顶peek元素不等于c,就把当前元素c入栈push到栈中,如果栈顶peek元素等于c,就把栈顶元素pop出来。for循环结束后,栈中剩余的元素就是我们要的结果集,把他们一个个出栈存到字符串里就行。

3.注意点

        由于最后结果集出栈的时候,出栈的字符顺序和我们要的是相反的,所以当栈不空时,可以循环用StringBuild逐个append出栈元素,最后再返回sb.reverse().toString()就行。

150.逆波兰表达式求值

题目

        给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

代码

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();

        for(String s : tokens){
            //如果是算法符合,就把栈顶的两个元素pop出来,计算后再push回去
            if(s.equals("+")){
                int x2 = stack.pop();
                int x1 = stack.pop();
                stack.push(x1 + x2);
            }
            else if(s.equals("-")){
                int x2 = stack.pop();
                int x1 = stack.pop();
                stack.push(x1 - x2);
            }
            else if(s.equals("*")){
                int x2 = stack.pop();
                int x1 = stack.pop();
                stack.push(x1 * x2);
            }
            else if(s.equals("/")){
                int x2 = stack.pop();
                int x1 = stack.pop();
                stack.push(x1 / x2);
            }
            //如果s不是算术符号,s是数字,就把s转为Integer再push进去
            else{
                stack.push(Integer.valueOf(s));
            }
        }
        //最后栈内的元素就是计算结果
        return stack.pop();
    }
}

总结

1.思想

        逆波兰表达式就是把数字写前面,计算符号写后面的一种计算式。它的计算方法是,如果遇到计算符号,就把该计算符号的前两个数字用该符号进行计算,直到用完每一个计算符号。因此,我们可以用栈存储数字,遇到计算符号,就把栈顶的两个数字出栈计算,计算完再入栈。

2.算法流程

        遍历String数组,如果当前字符串s是“+”,就把栈顶的两个元素pop出来,用x2和x1存储,计算x1+x2结果,把x1+x2再push进栈。其他的“-”、“*”、“/”原理一样,再写三个else语句就行。

        如果当前字符串s是数字,就把s转为Integer整型后push到栈中。最后栈内的元素就是计算结果。

3.注意点

(1)出栈获取两个x1和x2计算时,第一个出栈元素是x2,第二个出栈元素是x1,计算时x1在前x2在后,不能反过来哦。

(2)这里的tokens是字符串数组,不是字符串,因此遍历时,有下面两种方式:

        ①用String进行增强for,写法是String s : tokens

        ②用普通的for,写法是for(int i=0; i < tokens.length; i++) ,然后String s = tokens[i];

如果是String字符串,而不是字符串数组,才能用下面这种写法:

4.语法点

(1)判断两个字符串是否相同,要用s1.equals(s2)。判断字符char是否相同,才能用==。

(2)把String转为Integer,用Integer i = Integer.valueOf(str),注意O要大写。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-13 23:18:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-13 23:18:01       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-13 23:18:01       82 阅读
  4. Python语言-面向对象

    2024-04-13 23:18:01       91 阅读

热门阅读

  1. oracle rac打补丁后sqlplus / as sysdba ora-12537

    2024-04-13 23:18:01       33 阅读
  2. 巨坑:ModuleNotFoundError: No module named ‘dateutil‘

    2024-04-13 23:18:01       34 阅读
  3. GPT模型与知识图谱的融合之旅

    2024-04-13 23:18:01       41 阅读
  4. PTA 位运算

    2024-04-13 23:18:01       38 阅读
  5. 富格林:技巧抵抗曝光虚假套路

    2024-04-13 23:18:01       34 阅读
  6. 蓝桥杯-单片机组基础21——第15届省赛代码

    2024-04-13 23:18:01       32 阅读
  7. Linux C++ 033-STL之函数对象

    2024-04-13 23:18:01       31 阅读