代码随想录训练营D11-栈与队列篇 p2 |20. 有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

(一) 20. 有效的括号

栈的经典应用。

题目/文章/视频链接

1. 思路

1.1 直观思路

遍历读入s,每读一个字符时,先判断与栈顶元素能否凑一对,能凑一对,当前元素也不用入栈了,并且栈顶也顺便出栈;否则,当前元素入栈。
先读入的一定是左括号,并且消除时一定是右括号进入时。

写一个isMatch方法,用来判断’(‘、’)’ 等是一对的

1.2 代码随想录思路

没有考虑写isMatch方法,而是在起先存左括号时,就直接存的右括号,这样再右括号进入时可以直接判断两个字符是否相等,若相等则表明他们是一对的。
如何确定括号的左右呢?将([{三个括号都写在if中,else就是右括号。

有三种情况
1.匹配的过程中,发现栈空了,连字符都没了,返回false
2.匹配的过程中,发现当前字符与栈顶的不相等,返回false
3.字符串遍历完了,栈不为空,返回false

2. 代码

2.1 自己代码

class Solution {
    public boolean isValid(String s) {
        char[] chars = s.toCharArray();
        Stack<Character> stack = new Stack<>();
        for(char c : chars){
            if(!stack.isEmpty()){
                Character peek = stack.peek();
                if(isMatch(peek, c)){
                    stack.pop();
                    continue;
                }
            }
            stack.push(c);
        }
        return stack.isEmpty();
    }

    private boolean isMatch(char first, char second){
        return (first == '(' && second == ')')
                || (first == '[' && second == ']')
                || (first == '{' && second == '}');
    }
}

2.2 随想录代码

使用Deque表示栈,消耗更小一些,因为Deque是线程不安全的;而Stack是线程安全的。

public boolean isValid1(String s) {
    Deque<Character> deque = new ArrayDeque<>();
    char[] chars = s.toCharArray();

    for(char c : chars){
        if(c == '('){
            deque.push(')');
        }else if (c == '['){
            deque.push(']');
        }else if(c == '{'){
            deque.push('}');

        } else if(deque.isEmpty() || deque.peek() != c){//右括号会到这里
            //上述为第1、2种情况
            return false;
        }else{//栈不为空,而且还匹配上了,那就栈顶出栈
            deque.pop();
        }
    }
    //栈若不为空,则还有没匹配完的,也就是无效括号,false
    return deque.isEmpty();

}

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

栈的经典应用。

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

题目/文章/视频链接

1. 思路

与上一题代码随想录思路基本相同,只是这一题甚至不用做左括号到右括号的转换。

三种情况:
1.匹配时,栈中为空了或没匹配上,直接压栈。
2.匹配时,匹配上了,栈顶出栈

循环结束,出栈组成字符串并返回。

2. 代码

class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> deque = new ArrayDeque<>();
        char[] chars = s.toCharArray();

        for (char c : chars){
            if(deque.isEmpty() || deque.peek() != c){
                deque.push(c);
            }else {
                //匹配上了
                deque.pop();
            }
        }

        char[] result = new char[deque.size()];
        int i = 0;
        while(!deque.isEmpty()){
            result[i++] = deque.pop();
        }
        //reverse 数组
        int j = result.length - 1;
        i = 0;
        while(i < j){
            char temp = result[j];
            result[j] = result[i];
            result[i] = temp;
            ++i;
            --j;
        }
        return new String(result);

    }
}

(三) 150. 逆波兰表达式求值

本题不难,但第一次做的话,会很难想到,所以先看视频,了解思路再去做题

题目/文章/视频链接

1. 思路

一些小小的前置知识:

二叉树的遍历。都是指根结点的顺序。
先序遍历:根左右
后序遍历:左右根
中序遍历:左根右。
(1+2)*(3+4)对应的表达式)
中缀表达式(中序遍历):(1+2)*(3+4)
后缀表达式(后序遍历):12+34+*

中缀表达式:适合人类宝宝的表达式,并且离不开括号。
后缀表达式:适合计算机宝宝的表达式,不需要括号表示优先级。

2.思路:
后缀表达式,也是栈的经典应用。
创建一个栈。将String转为数组后,依次读入。
遇到数字就压栈,遇到’+‘、’-‘、’*’ 和 '/'运算符就弹出两个数字进行计算。
循环结束后,栈中应该有一个元素就是整个式子的运算结果。

3.细节
先入栈的(即后出栈的)在运算符的前面,在/或-时。

2. 代码


public int evalRPN(String[] tokens) {
    Deque<Integer> stack = new ArrayDeque<>();//直接创建数字类型的栈

    int first;
    for(String str : tokens){
        if("+".equals(str)){
            stack.push(stack.pop() + stack.pop());
        }else if("-".equals(str)){
            first = stack.pop();
            stack.push(stack.pop() - first);
        }else if("*".equals(str)){
            stack.push(stack.pop() * stack.pop());
        }else if("/".equals(str)){
            first = stack.pop();
            stack.push(stack.pop() / first);
        }else {
            //数字才会到这里,数字就压栈
            stack.push(Integer.valueOf(str));
        }
    }
    return stack.pop();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值