Day11 | 栈与队列 20. 有效的括号 / 1047. 删除字符串中的所有相邻重复项 / 150. 逆波兰表达式求值

Leetcode 20. 有效的括号

题目链接:20. 有效的括号

思路:

我想的是用两个队列,分别存储左括号和右括号,但是写起来判断条件太多了,而且浪费存储空间,肯定不是这么做的。

解题:失败

代码实现

class Solution {
    public boolean isValid(String s) {
        // 剪枝
        if(s.length() % 2 != 0){
            return false;
        }
        Deque<Character> stack = new LinkedList<>();
        char ch;

        for(int i = 0; i < s.length(); i++){
            ch = s.charAt(i);
            if(ch == '('){
                stack.push(')');
            }
            else if(ch == '{'){
                stack.push('}');
            }
            else if(ch == '['){
                stack.push(']');
            }
            else if(stack.isEmpty() || stack.peek() != ch){
                return false;
            }
            else{
                stack.pop();
            }
        }
        return stack.isEmpty();
    }
}

时间复杂度: O(n)
空间复杂度: O(n)

  1. 括号匹配是使用栈解决的经典问题。
  2. 由于栈结构的特殊性,非常适合做对称匹配类的题目。
  3. 技巧:在匹配左括号的时候,右括号先入栈,就只需要比较当前元素(右括号)和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了。

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

题目链接:1047. 删除字符串中的所有相邻重复项

思路:

本题要删除相邻相同元素,相对于 20.有效的括号 来说其实也是匹配问题,20.有效的括号 是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作。
写了上面那一题后,这一题就有思路了。匹配问题都是栈的强项,以后看到匹配问题,第一时间要想到栈

解题:成功

代码实现

解法一

class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> deque = new LinkedList<>();
        char ch;
        for(int i = 0; i < s.length(); i++){
            ch = s.charAt(i);
            if(!deque.isEmpty() && deque.peekLast() == ch){
                deque.pollLast();
            }
            else{
                deque.offerLast(ch);
            }
        }
        String res = "";
        while(!deque.isEmpty()){
            res += deque.pollFirst();
        }
        return res;
    }
}

解法二:
可以拿字符串直接作为栈,这样省去了栈还要转为字符串的操作。

class Solution {
    public String removeDuplicates(String s) {
        StringBuilder res = new StringBuilder();
        char ch;
        // top为res的长度
        int top = -1;
        for(int i = 0; i < s.length(); i++){
            ch = s.charAt(i);
            if(top < 0 || res.charAt(top) != ch){
                res.append(ch);
                top++;
            }
            else{
                res.deleteCharAt(top);
                top--;
            }
        }
        return res.toString();
    }
}

字符串删除最后一个字符的几种方法:

  1. substring(0, str.length() - 1)
  2. stringBuilder.deleteCharAt(str.length() - 1)

Leetcode 150. 逆波兰表达式求值

题目链接:150. 逆波兰表达式求值

思路:

逆波兰表达式相当于是二叉树中的后序遍历,后缀表达式对计算机来说是非常友好的。

解题:失败

代码实现

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> deque = new LinkedList<>();
        for(String s : tokens){
            if("+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s)){
                int a = deque.pollLast();
                int b = deque.pollLast();
                if(s.equals("+")){
                    deque.offerLast(b + a);
                }
                else if(s.equals("-")){
                    deque.offerLast(b - a);
                }
                else if(s.equals("*")){
                    deque.offerLast(b * a);
                }
                else{
                    deque.offerLast(b / a);
                }
            }
            else{
                deque.offerLast(Integer.parseInt(s));
            }
        }
        return deque.pollLast();
    }
}

我写的代码一直报错,然后发现是这个判断语句的问题 if(!Character.isDigit(s.charAt(0))),因为如果是负数的话,这个判断条件也成立。

总结

栈为什么适合做这种类似于爱消除的操作,因为栈帮助我们记录了遍历数组当前元素时候,前一个元素是什么。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值