Leetcode 20. 有效的括号
题目链接:20. 有效的括号
思路:
我想的是用两个队列,分别存储左括号和右括号,但是写起来判断条件太多了,而且浪费存储空间,肯定不是这么做的。
解题:失败
代码实现
class Solution {
public boolean isValid(String s) {
// 剪枝
if(s.length() % 2 != 0){
return false;
}
Deque<Character> stack = new LinkedList<>();
char ch;
for(int i = 0; i < s.length(); i++){
ch = s.charAt(i);
if(ch == '('){
stack.push(')');
}
else if(ch == '{'){
stack.push('}');
}
else if(ch == '['){
stack.push(']');
}
else if(stack.isEmpty() || stack.peek() != ch){
return false;
}
else{
stack.pop();
}
}
return stack.isEmpty();
}
}
时间复杂度: O(n)
空间复杂度: O(n)
- 括号匹配是使用栈解决的经典问题。
- 由于栈结构的特殊性,非常适合做对称匹配类的题目。
- 技巧:在匹配左括号的时候,右括号先入栈,就只需要比较当前元素(右括号)和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了。
Leetcode 1047. 删除字符串中的所有相邻重复项
题目链接:1047. 删除字符串中的所有相邻重复项
思路:
本题要删除相邻相同元素,相对于 20.有效的括号 来说其实也是匹配问题,20.有效的括号 是匹配左右括号,本题是匹配相邻元素,最后都是做消除的操作。
写了上面那一题后,这一题就有思路了。匹配问题都是栈的强项,以后看到匹配问题,第一时间要想到栈。
解题:成功
代码实现
解法一
class Solution {
public String removeDuplicates(String s) {
Deque<Character> deque = new LinkedList<>();
char ch;
for(int i = 0; i < s.length(); i++){
ch = s.charAt(i);
if(!deque.isEmpty() && deque.peekLast() == ch){
deque.pollLast();
}
else{
deque.offerLast(ch);
}
}
String res = "";
while(!deque.isEmpty()){
res += deque.pollFirst();
}
return res;
}
}
解法二:
可以拿字符串直接作为栈,这样省去了栈还要转为字符串的操作。
class Solution {
public String removeDuplicates(String s) {
StringBuilder res = new StringBuilder();
char ch;
// top为res的长度
int top = -1;
for(int i = 0; i < s.length(); i++){
ch = s.charAt(i);
if(top < 0 || res.charAt(top) != ch){
res.append(ch);
top++;
}
else{
res.deleteCharAt(top);
top--;
}
}
return res.toString();
}
}
字符串删除最后一个字符的几种方法:
- substring(0, str.length() - 1)
- stringBuilder.deleteCharAt(str.length() - 1)
Leetcode 150. 逆波兰表达式求值
题目链接:150. 逆波兰表达式求值
思路:
逆波兰表达式相当于是二叉树中的后序遍历,后缀表达式对计算机来说是非常友好的。
解题:失败
代码实现
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> deque = new LinkedList<>();
for(String s : tokens){
if("+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s)){
int a = deque.pollLast();
int b = deque.pollLast();
if(s.equals("+")){
deque.offerLast(b + a);
}
else if(s.equals("-")){
deque.offerLast(b - a);
}
else if(s.equals("*")){
deque.offerLast(b * a);
}
else{
deque.offerLast(b / a);
}
}
else{
deque.offerLast(Integer.parseInt(s));
}
}
return deque.pollLast();
}
}
我写的代码一直报错,然后发现是这个判断语句的问题 if(!Character.isDigit(s.charAt(0))),因为如果是负数的话,这个判断条件也成立。
总结
栈为什么适合做这种类似于爱消除的操作,因为栈帮助我们记录了遍历数组当前元素时候,前一个元素是什么。