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

栈的经典应用

括号匹配是使用栈解决的经典问题。

栈解决括号匹配:相邻的括号匹配了,则做相应的消除,匹配的动作

写代码之前要分析好有哪几种不匹配的情况

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false

第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配

但还有一些技巧,在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了!

Q&A:

Q:什么叫以正确的顺序闭合?[ { } ( ] ) 比如如果是这样就过不了,[ { } ( ) ]这样才能过吗?

A:是的。大概指的就是先遍历到的后闭合,后遍历到的先闭合吧。先这样吧,理解代码就行,不要抠字眼。

左括号对应右边括号,一定要左右都互相对应(){}[]

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

import java.util.LinkedList;

public class ValidParentheses {
    public boolean isValid(String s){
        //字母character
        LinkedList<Character> stack = new LinkedList<Character>();
        for (char c : s.toCharArray()){
            //正常都匹配的情况:遇到左括号,把对应右括号入栈
            if(c ==  '('){
                stack.push(')');
            }else if(c ==  '['){
                stack.push(']');
            }else if(c ==  '{') {
                stack.push('}');
                //不匹配情况:1。遇到右括号,发现与栈顶元素不匹配stack.pop()!=c
                //不匹配情况:2。遇到右括号,此时栈为空,无法匹配stack.isEmpty()
                //tips:以上两个情况不能反过来,否则要报空指针
            }else if(stack.isEmpty() || stack.pop()!=c){
                return false;
            }
        }
        //遍历完之后,栈不为空,直接return false
        //正常都匹配的情况下,遍历完栈为空
        //所以,字符串遍历完之后,判断栈是否为空,就是判断正常匹配还是非正常匹配
        return stack.isEmpty();

    }
}

class Solution {
    public boolean isValid(String s) {
        Deque<Character> deque = new LinkedList<>();
        char ch;

        for(int i = 0; i < s.length(); i++){
            ch = s.charAt(i);
            if(ch == '('){
                deque.push(')');
            }else if(ch == '{'){
                deque.push('}');
            }else if(ch == '['){
                deque.push(']');
                //栈为空或者栈顶元素不等于当前遍历的字符串
            }else if(deque.isEmpty()|| deque.peek() != ch){
                return false;
            }else{
                //第一种,遍历的字符串等于栈顶元素
                deque.pop();
            }
        }
        //第一种,遍历完字符串一定为空,如果不为空就是return false
        return deque.isEmpty();

    }
}

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

栈的经典应用。

本题要删除相邻相同元素,相对于20. 有效的括号 (opens new window)来说其实也是匹配问题,20. 有效的括号 是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作

相邻的字母相同,做消除的动作

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

StringBuilder 对象类似于 String 对象,但可以修改它们。

import java.util.LinkedList;

public class RemoveAllAdjacentDuplicatesInString {
    public String removeDuplicates(String s){
        LinkedList<Character> stack = new LinkedList<>();
        for(char c : s.toCharArray()){
            if(stack.isEmpty() || stack.peek() != c ){
                stack.push(c);
                continue;
            }else {
                //与栈中元素相等,则栈里元素弹出
                stack.pop();
            }
        }
        StringBuilder sb = new StringBuilder();
        for(char c: stack){
            sb.append(c);
        }
        sb.reverse();//把栈里元素翻转
        return sb.toString();
    }
}
class Solution {
    public String removeDuplicates(String s) {
        //字符串模拟栈
        //拿字符串直接作为栈,省去了栈还要转为字符串的操作
        //使用deque作为堆栈
        //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. 逆波兰表达式求值

// Deque 接口继承了 Queue 接口
    // 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
import java.util.Stack;

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

        for(String str : tokens){
            if(!"+-*/".contains(str)){//如果是数字就入栈
                int num = Integer.parseInt(str);//string数字转int数字
                stack.push(num);
            }else {
                //符号就把元素(数字)弹出来,stack是后进先出
                int num1 = stack.pop();
                int num2 = stack.pop();
                if(str.equals("+")){
                    stack.push(num1 + num2);
                }else if(str.equals("-")){
                    stack.push(num2 - num1);
                }else if(str.equals("*")) {
                    stack.push(num1 * num2);
                }else {
                    stack.push(num2 / num1);
                }
            }
        }
        return stack.pop();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值