20. 有效的括号
判断括号是否成对出现,如果出现左括号的话,就把相应的右括号放进栈里,然后对于出现右括号,就进行匹配,对于不匹配,这里有三种情况:
1.“[]({)}”栈中有括号,但是栈首元素和当前的右括号不相同。
2.“({}))”栈中已经为空,说明右括号过多,匹配不了
3.“((({})”遍历结束后,发现栈不为空,说明左括号过多,无法匹配,这个放到循环外面进行即可。
如果匹配的话,就将栈首元素弹出来匹配。
class Solution {
public boolean isValid(String s) {
Stack<Character> t = new Stack<>();
if (s.length() % 2 != 0)
return false;
// 遇到左括号就把右括号入栈
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
t.push(')');
} else if (c == '{') {
t.push('}');
} else if (c == '[') {
t.push(']');
} // 遇到右括号但是和栈里元素不匹配或者栈已经是空
else if (t.isEmpty() || c != t.peek()) {
return false;
} else {// 右括号和栈顶元素匹配
t.pop();
}
}
// 遍历结束但是栈中仍然有元素,证明没有匹配上
return t.isEmpty();
}
}
1047. 删除字符串中的所有相邻重复项
这道题也是用栈的思想来做,栈首的字母和字符串中的字母不重复就放进栈里,重复的就不放,顺便将栈首元素弹出。注意讨论一下栈是否为空的条件,因为当栈为空的时候,没办法取到栈首的元素。
str = t.pop() + str;
最后将栈内的元素转化为字符串的时候,注意栈是先进后出,所以将后出来的元素放到前面,顺序才正确。
class Solution {
public String removeDuplicates(String s) {
ArrayDeque<Character> t = new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
// 栈为空或者没出现重复字母
if (t.isEmpty() || t.peek() != ch) {
t.push(ch);
} else if (t.peek() == ch) {
t.pop();
}
}
// 从后往前放
/*
* char[] r = new char[t.size()];
* for (int i = t.size() - 1; i >= 0; i--) {
* r[i] = t.pop();
* }
*/
String str = "";
while (!t.isEmpty()) {
// 注意前后顺序,栈是先入后出,将之前出来的放在后面
str = t.pop() + str;
}
return str;
}
}
150. 逆波兰表达式求值
逆波兰式的实质是树的后序遍历,中心思想就是遇到运算符就弹出两个数字,然后将运算后的结果再放入栈中。这是注意到数字的前后顺序对运算的结果有影响的是减法和除法,所以弹出的第一个数字是运算中的后面的数字,所以用num2代表弹出的第一个元素。遇到的数字就正产入栈即可。最后将栈中最后一个数字返回弹出即可。注意这里的测试案例是合法的,无序考虑异常情况。
class Solution {
public int evalRPN(String[] tokens) {
// 逆波兰表达式就是二叉树的后续遍历
Stack<Integer> s = new Stack<>();
for (String token : tokens) {
// 遇到字符就弹出两个数字
if (token.equals("+") || token.equals("-") || token.equals("*") || token.equals("/")) {
if (token.equals("+")) {
// 注意顺序,第一个进去的是运算中后面的那位
int num2 = s.pop();
int num1 = s.pop();
s.push(num1 + num2);
} else if (token.equals("-")) {
int num2 = s.pop();
int num1 = s.pop();
s.push(num1 - num2);
} else if (token.equals("*")) {
int num2 = s.pop();
int num1 = s.pop();
s.push(num1 * num2);
} else if (token.equals("/")) {
int num2 = s.pop();
int num1 = s.pop();
s.push(num1 / num2);
}
}
// 如果是数字的话,正常入栈即可
else {
s.push(Integer.valueOf(token));// 将字符串转化为整数
}
}
return s.pop();
}
}