代码随想录第九天|有效的括号|删除字符串中的所有相邻重复项 |逆波兰表达式求值

今天是栈的应用练习,通过这几题可以发现,栈非常适合“消消乐”类型的问题,消除相邻相同元素,因为栈能够记录当前元素的同时还能记录当前元素的上一个元素。

有效的括号

首先分析会出现几种不符合条件的情况-总共是三种,一种是左括号多余,一种是左右括号不匹配,还有一种是右括号多余。在这里,如果将所有括号全部压入栈中的话,通过弹出的括号来进行判断的话会比较复杂。这里有一种巧妙的办法,从左到右,遇到左括号时往栈中压入右括号,当遇到右括号时,弹出栈顶元素与其匹配,若是不匹配,则是属于情况二;若是匹配则弹出栈顶元素,继续匹配判断,直到遍历完所有括号;若最后栈不为空,则出现了括号多余的情况,若为空,则返回true;因为从左到右只会先是左括号再是右括号,若是一开始就是右括号,那这里就没有左括号能与其匹配,属于右括号多余的情况;

这里还有一种技巧,就是在遇到右括号时,正面需要判断是哪一种右括号,而且要判断是否匹配,写起来十分麻烦,这里先写出不符合条件不匹配的右括号的情况,剩下直接一个else即可包含所有需要讨论的正面匹配的情况。当遇到正面讨论情况比较多比较复杂的时候,从反面入手,反面条件就会比较少,讨论完反面条件后一个else即可包含所有正面条件。

class Solution {
    public boolean isValid(String s) {
        ArrayDeque<Character> stack=new ArrayDeque<>();
        char[] arr=s.toCharArray();
        for(int i=0;i<arr.length;i++){
            if(arr[i]=='('){
                stack.addFirst(')');
            }else if(arr[i]=='{'){
                stack.addFirst('}');
            }else if(arr[i]=='['){
                stack.addFirst(']');
            }else if(stack.isEmpty()||arr[i]!=stack.peekFirst()){ //非常巧妙,反向讨论
                    return false;              //正面右括号不好讨论时,讨论其反例
            }else{
                stack.removeFirst();
            }
    
        }
        return stack.isEmpty();
    }
}

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

这题和上一题括号匹配方法相同,将字符往栈中压入,再压入的时候判断当前元素与栈顶元素,若相同则将栈顶元素弹出,若不同则继续压入。最后剩下栈中的元素,将栈中元素弹出逆序输出即可。这里逆序输出也是一个小技巧,运用字符连接符“+”,将每一个弹出栈的元素放在字符串的前端。

class Solution {
    public String removeDuplicates(String s) {
        ArrayDeque<Character> stack=new ArrayDeque<>();
        for(int i=0;i<s.length();i++){
            if(!stack.isEmpty()&&s.charAt(i)==stack.peekFirst()){
                stack.removeFirst();
            }else{
                stack.addFirst(s.charAt(i));
            }
            
        }
        String str=""; //使用一个空字符串通过将栈顶元素连接起来返回
        while(!stack.isEmpty()){
            str=stack.removeFirst()+str;//这里栈顶元素放在字符串最前面
        }
        return str;

    }
}

逆波兰表达式求值

该题的思路就是遇到数字时将其压入栈中,遇到运算符号时,取出两个栈顶元素进行运算。相除和相减时要注意栈顶元素的顺序,后出栈的元素是除数和减数。

这里同样是一种讨论字符是否为数字的正面情况不好讨论,从反面入手的方法。

class Solution {
    public int evalRPN(String[] tokens) {
        ArrayDeque<Integer> stack=new ArrayDeque<>();
        for(int i=0;i<tokens.length;i++){
            if("+".equals(tokens[i])){//正面为数字时加入栈中不好写,反面条件较少,从反面写
                stack.addFirst(stack.removeFirst()+stack.removeFirst());
            }else if("-".equals(tokens[i])){
                stack.addFirst(-(stack.removeFirst()-stack.removeFirst()));
            }else if("*".equals(tokens[i])){
                stack.addFirst(stack.removeFirst()*stack.removeFirst());
            }else if("/".equals(tokens[i])){
                int temp1=stack.removeFirst();
                int temp2=stack.removeFirst();
                stack.addFirst(temp2/temp1);
            }else {
                stack.addFirst(Integer.valueOf(tokens[i]));
            }
        }
        return stack.removeFirst();
    }
}

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值