文章目录
栈与队列Part2
一、20. 有效的括号
1. 思路分析
- 原理:栈先入后出特点恰好与本题括号排序特点一致,即若遇到左括号入栈,遇到右括号时将对应栈顶左括号出栈,则遍历完所有括号后 stack 仍然为空。
经过分析,本题有三种错误情况:
- 左括号冗余:遍历过后得到的栈不为空。
- 右括号冗余:遍历到右括号时,栈已经空了。
- 括号类型不匹配:栈顶字符与当前字符不匹配。
2. 解法分析
大概就是遍历,入栈或者匹配。最后再判个空。
3. 代码展示
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
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 (stack.empty())
return false; // 无左括号配对
if (stack.peek() != s.charAt(i))
return false; // 类型不匹配
stack.pop();
}
}
return stack.empty(); // 有无右括号配对。简洁写法。
}
}
二、1047. 删除字符串中的所有相邻重复项
1. 思路分析
本题是很经典的对于栈结构的应用。原理显而易见,区别在具体的实现方法
2. 解法分析
比较好的优化算法是,创建一个StringBuffer,并将其作为一个栈来用。最后消除出来的就是我们需要的结果。
与我第一时间想到的方案相比,现在的算法对StringBuffer的增删操作都是 O ( 1 ) O(1) O(1),非常省时。
以及StringBuffer的删除单个字符方法名为deleteCharAt().
3. 代码展示
class Solution {
public String removeDuplicates(String s) {
// 将 StringBuffer 当做栈
StringBuffer sb = new StringBuffer();
// top为 sb 的长度
int top = -1;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--
if (top >= 0 && sb.charAt(top) == c) {
sb.deleteCharAt(top);
top--;
// 否则,将该字符 入栈,同时top++
} else {
sb.append(c);
top++;
}
}
return sb.toString();
}
}
三、150. 逆波兰表达式求值
1. 思路分析
早在去年就已经被栈计算器反反复复磨了好久,逆波兰的输入简化了括号问题,真的简单了很多。由于不用担心异常处理,所以写起来也很顺畅。
2. 解法分析
几点注意:
- Java中’'表示基本数据类型字符,而""才能表示字符串。
和字符串作比较要用"",以及.equals()。 - parseInt()方法返回基本数据类型int,而valueOf()方法返回Integer对象。
3. 代码展示
class Solution {
public int evalRPN(String[] tokens) {
// 应该...不用做异常处理吧
Stack<Integer> stack = new Stack<>();
for (String s : tokens) {
// Java中''表示基本数据类型字符,而""才能表示字符串。
// 和字符串作比较要用""
if (s.equals("+")) {
int sr = stack.pop();
int sl = stack.pop();
stack.push(sr + sl);
}
else if (s.equals("-")) {
int sr = stack.pop();
int sl = stack.pop();
stack.push(sl - sr);
}
else if (s.equals("*")) {
int sr = stack.pop();
int sl = stack.pop();
stack.push(sl * sr);
}
else if (s.equals("/")) {
int sr = stack.pop();
int sl = stack.pop();
stack.push(sl / sr);
}
else {
// parseInt()方法返回基本数据类型int,而valueOf()方法返回Integer对象。
stack.push(Integer.parseInt(s));
}
}
return stack.peek();
}
}
四、总结
爱栈。