20. 有效的括号
根据栈的特性,非常适合做对称匹配类的题目
而“有效的括号”便是使用栈解决的经典问题
代码如下:
class Solution {
public boolean isValid(String s) {
Stack<Character> left = new Stack<>();
for(char c : s.toCharArray()){
if(c == '(' || c == '{' || c == '['){
left.push(c);
}else{ // 当遍历到右括号
if(!left.isEmpty() && left.peek() == leftOf(c)){
left.pop();
}else{ // 和最近的左括号不匹配
return false;
}
}
}
// 是否所有的左括号都已经进行匹配
return left.isEmpty();
}
public char leftOf(char c){
if(c == ')') return '(';
if(c == '}') return '{';
return '[';
}
}
1047. 删除字符串中的所有相邻重复项
要知道栈为什么适合做这种类似于爱消除的操作,因为栈帮助我们记录了 遍历数组当前元素时候,前一个元素是什么。
代码如下:
class Solution {
public String removeDuplicates(String s) {
StringBuilder sb = new StringBuilder(); // 利用StringBuilder模拟栈
int pre = sb.length() - 1; // 定义一个指向字符串中前一个字符的指针
for(int i = 0;i<s.length();i++){
char c = s.charAt(i);
// 当 sb 不为空并且前一个字符与当前字符相同,需要进行删除操作
if(pre >= 0 && c == sb.charAt(pre)){
sb.deleteCharAt(pre);
// 删除字符后将指针前移
pre--;
}else{ // 相邻字符不同
sb.append(c);
pre++;
}
}
return sb.toString();
}
}
150. 逆波兰表达式求值
按顺序遍历逆波兰表达式中的字符,如果是数字,则放入栈;如果是运算符,则将栈顶的两个元素拿出来进行运算,再将结果放入栈。对于减法和除法,运算顺序别搞反了,栈顶第二个数是被除(减)数。
所以这题很简单,直接按照运算规则借助栈计算表达式结果即可。
代码如下:
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stk = new Stack<>();
for(String token : tokens){
if("+-*/".contains(token)){ // 判断是否是运算符号
int a = stk.pop();
int b = stk.pop();
switch(token){ // 需注意 "-" "/" 弹出栈顶元素时需注意运算顺序
case "+":
stk.push(b + a);
break;
case "-":
stk.push(b - a);
break;
case "*":
stk.push(b * a);
break;
case "/":
stk.push(b / a);
break;
}
}else{ // 不是运算符号,则直接入栈
stk.push(Integer.parseInt(token));
}
}
return stk.pop();
}
}