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