Day11 有效的括号+删除字符串中的所有相邻重复项+逆波兰表达式求值

文章介绍了如何使用栈结构解决编程问题,包括检查有效括号、删除字符串中的所有相邻重复项以及计算逆波兰表达式的值。对于有效括号,通过匹配左右括号实现;删除重复项时,使用栈或双端队列;逆波兰表达式则通过栈处理运算符和数值,无需考虑运算优先级。
摘要由CSDN通过智能技术生成

代码随想录算法训练营第11天 | 20.有效的括号、1047.删除字符串中的所有相邻重复项、150.逆波兰表达式求值

20.有效的括号

题目链接

思路:

栈结构的特殊性,非常适合做对称匹配类的题目
写代码前分析题目,有三种不匹配的情况:

  1. 第一种情况,字符串里左方向的括号多余了 ,所以不匹配。 括号匹配1
  2. 第二种情况,括号没有多余,但是 括号的类型没有匹配上。 括号匹配2
  3. 第三种情况,字符串里右方向的括号多余了,所以不匹配。 括号匹配3

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

代码部分:

class Solution {
    public boolean isValid(String s) {
        Stack<Character> st = new Stack<>();
        for(int i = 0; i<s.length(); i++){
            if(s.charAt(i) == '('){
                st.push(')');
            }else if(s.charAt(i) == '['){
                st.push(']');
            }else if(s.charAt(i) == '{'){
                st.push('}');
            // 思考 &&
            }else if(!st.isEmpty() && st.peek() == s.charAt(i)){
                st.pop();
            }else{
                return false;
            }
        }
        // if(st.isEmpty())    return true;
        // else    return false;
        return st.isEmpty();
    }
}

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

题目链接

思路:

在这里插入图片描述

补充:
实现函数递归调用就需要栈,但不是每种编程语言都支持递归,例如:
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。

代码部分:

第一种写法
class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> st = new Stack<>();
        for(int i = 0; i<s.length(); i++){
            if(st.isEmpty() || s.charAt(i) != st.peek()){
                st.push(s.charAt(i));
            }else{
                st.pop();
            }
        }
        // Stack ==> String
        String str = "";
        while(!st.isEmpty()){
            str = st.pop() + str;
        }
        return str;
    }
}
第二种写法(使用 Deque 作为堆栈)
```
class Solution {
    public String removeDuplicates(String S) {
        //ArrayDeque会比LinkedList在除了删除元素这一点外会快一点
        //参考:https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlist
        ArrayDeque<Character> deque = new ArrayDeque<>();
        char ch;
        for (int i = 0; i < S.length(); i++) {
            ch = S.charAt(i);
            if (deque.isEmpty() || deque.peek() != ch) {
                deque.push(ch);
            } else {
                deque.pop();
            }
        }
        String str = "";
        //剩余的元素即为不重复的元素
        while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        return str;
    }
}
```

150.逆波兰表达式求值

题目链接

思路:

加和除的时候要注意那个是被减数和被除数。
在这里插入图片描述

补充:
我们习惯看到的表达式都是中缀表达式,因为符合我们的习惯,但是中缀表达式对于计算机来说就不是很友好了。
例如:4 + 13 / 5,这就是中缀表达式,计算机从左到右去扫描的话,扫到13,还要判断13后面是什么运算符,还要比较一下优先级,然后13还和后面的5做运算,做完运算之后,还要向前回退到 4 的位置,继续做加法,你说麻不麻烦!

那么将中缀表达式,转化为后缀表达式之后:[“4”, “13”, “5”, “/”, “+”] ,就不一样了,计算机可以利用栈来顺序处理,不需要考虑优先级了。也不用回退了, 所以后缀表达式对计算机来说是非常友好的。

代码部分:

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> st = new Stack<>();
        //Deque<Integer> st= new LinkedList();
        Integer op1, op2;
        
        for (String s : tokens) {
          switch (s) {
          case "+":
            st.push(st.pop() + st.pop());
            break;
          case "-":
            op2 = st.pop();
            op1 = st.pop();
            st.push(op1 - op2);
            break;
          case "*":
            st.push(st.pop() * st.pop());
            break;
          case "/":
            op2 = st.pop();
            op1 = st.pop();
            st.push(op1 / op2);
            break;
          default:
            st.push(Integer.valueOf(s));
            break;
          }
        }
        return st.pop();
    }
}
  1. switch代替if-else,效率更优
  2. Integer.parseInt代替Integer.valueOf,减少自动拆箱装箱操作
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值