算法day11 | 队列和栈:栈的应用

1. 用栈完成括号匹配

1.1 链接

https://leetcode.cn/problems/valid-parentheses

1.2 关键知识点

  • Java中用来表达的功能(push/pop/peek),更适用的是使用双端队列接口Deque,并用实现类ArrayDeque/LinkedList来进行初始化。Deque是一个双端队列接口,继承自Queue接口,Deque的实现类是LinkedList、ArrayDeque、LinkedBlockingDeque,其中LinkedList是最常用的。有方法push\pop和读方法peek()\isEmpty()
Deque<Integer> stack = new ArrayDeque<>();
Deque<Integer> stack = new LinkedList<>();
  • Java中用来表达队列的功能
Queue<Integer> queue= = new LinkedList<>();

注意:Java堆栈Stack类已经过时,Java官方推荐使用Deque替代Stack使用。Deque堆栈操作方法:push()、pop()、peek()。

1.3 自己遇到的细节问题

  • 创建栈对象,括号里面应该是char的包装类Character,而不是char
  • 字符串相关问题,由于String不可变,在java中经常要借助一个新的变量来解决
Deque<Character> stack = new LinkedList<>();

1.4 题解

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

        for(int i = 0;i < s.length(); i ++){
            if(s.charAt(i) == '('){
                stack.push(')');
            }else if(s.charAt(i) == '{'){
                stack.push('}');
            }else if(s.charAt(i) == '['){
                stack.push(']');
            }else if(s.charAt(i) == ']'|| s.charAt(i) == ')' || s.charAt(i) == '}'){
                if(stack.isEmpty()){
                    return false;//1右边多余
                }else if(s.charAt(i) != stack.peek()){
                    return false;//2不匹配
                }else{
                    stack.pop();//匹配
                }
            }    
        } 

        if(!stack.isEmpty()){ 
            return false;//3左边有多的括号
        }else{
            return true;
        }
        
    }
}

2.用栈完成删除字符串中的所有相邻重复项

2.1 链接

https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string

2.2 关键知识点

2.3 自己遇到的细节问题

  • 栈转为字符串:
  String rsStr = "";
  while(!rs.isEmpty()){
      rsStr = rs.pop() + rsStr;//注意字符串相加有顺序
  }
  • 本道题还可以拿字符串直接作为栈(StringBuilder),省去了栈还要转为字符串的操作。

2.4 题解

class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> rs = new LinkedList<>();
        for(int i = 0; i < s.length(); i ++){
            char ch = s.charAt(i);
            if((!rs.isEmpty()) && (ch == rs.peek())){
                rs.pop();
            }else{
                rs.push(ch);
            }
        }
        String rsStr = "";
        while(!rs.isEmpty()){
            rsStr = rs.pop() + rsStr;//注意字符串相加有顺序
        }
        return rsStr;
    }
}

3.用栈完成逆波兰表达式求值

3.1 链接

https://leetcode.cn/problems/evaluate-reverse-polish-notation/

3.2 关键知识点

了解逆波兰表达式(后缀表达式)类似于二叉树计算。后序遍历。逆波兰表达式是用后序遍历的方式把二叉树序列化了。

  • 这道题的关键是
    • 要把前面算的结果作为结果保存下来,放在原来的位置进行接下来的运算:类似递归( 递归就是用栈来实现的)
  • 逆波兰表达式主要有以下两个优点:
    • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
    • 适合用栈操作运算:遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中

3.3 自己遇到的细节问题

  • String转为int: Integer.valueOf(s)
  • String相等是equals 有s
  • 注意输入的类型,string类型相等的判断是equal
  • 注意栈pop的顺序和输入相反,减法和除法需要反过来

3.4 题解

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> exp = new LinkedList<>();
        for(String ch : tokens){
            if(ch.equals("+")){
                int num1 = exp.pop();
                int num2 = exp.pop();
                exp.push(num1 + num2);
            }else if(ch.equals("-")){
                int num1 = exp.pop();
                int num2 = exp.pop();
                exp.push(num2- num1);    //减需要注意顺序,栈pop的顺序和输入相反        
            }else if(ch.equals("*")){
                int num1 = exp.pop();
                int num2 = exp.pop();
                exp.push(num1 * num2);            
            }else if(ch.equals("/")){
                int num1 = exp.pop();
                int num2 = exp.pop();
                exp.push(num2 / num1);    //除需要注意顺序,栈pop的顺序和输入相反,向下取整/即可        
            }else{
                exp.push(Integer.valueOf(ch));
            }
        }
        return (exp.pop());
    }
}

4.总结

上面这些问题用数组等可能也能完成,但由于其题目特点(对称匹配/每一个子表达式要得出一个结果,然后拿这个结果再进行运算,类似递归),借助栈结构的特性,可以用简单的方法就解决

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值