第五章 栈与队列part02
大纲
● 20. 有效的括号
● 1047. 删除字符串中的所有相邻重复项
● 150. 逆波兰表达式求值
leetcode 20
有效的括号
思路
- 可类型括号的相互匹配 自然想到了栈 左括号进栈 遇到右括号出栈
细节
- 注意当栈中的左括号遇到不匹配的右括号返回false
- 注意为空栈时遇到右括号的边界情况的判断
代码
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
switch (c) {
case '(':
case '[':
case '{': {
stack.push(c);
break;
}
case '}' : {
if (stack.isEmpty() || stack.peek() != '{') return false;
else stack.pop();
break;
}
case ']' : {
if (stack.isEmpty() || stack.peek() != '[') return false;
else stack.pop();
break;
}
case ')' : {
if (stack.isEmpty() || stack.peek() != '(') return false;
else stack.pop();
break;
}
}
}
return stack.isEmpty();
}
}
复杂度
- 时间
O(n)
- 空间
O(n)
leetcode 1047
删除字符串中的所有相邻重复项
思路
- 根据题目删除当前相邻的重复字符串 自然想到了使用栈来遍历此字符串
细节
- 注意进栈的时机为栈空 出栈的时机为当前栈顶元素和当前遍历元素相同
代码
class Solution {
public String removeDuplicates(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (!stack.isEmpty() && stack.peek() == c) stack.pop();
else stack.push(c);
}
StringBuilder sb = new StringBuilder();
for (char c : stack) sb.append(c);
return sb.toString();
}
}
复杂度
- 时间
O(n)
- 空间
O(n)
leetcode 150
逆波兰表达式求值
思路
- 经典的栈应用题 遇到数字存储 遇到操作符取栈顶两元素做运算
细节
- 注意操作符是有左右操作之分的 如减法和除法 需要额外注意栈元素的位置
- 注意当前作为运算的值也要存储到栈中
代码
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
String s = tokens[i];
if ("+".equals(s)) stack.push(stack.pop() + stack.pop());
else if ("*".equals(s)) stack.push(stack.pop() * stack.pop());
else if ("-".equals(s)) stack.push(- (stack.pop() - stack.pop()));
else if ("/".equals(s)) {
int a = stack.pop(), b = stack.pop();
stack.push(b / a);
} else stack.push(Integer.parseInt(s));
}
return stack.pop();
}
}
复杂度
- 时间
O(n)
- 空间
O(n)