20. 有效的括号
第一想法
没啥想法
想了想双指针和哈希表map,感觉都太复杂了
思路
栈非常适合做对称匹配类型的题目
这道题可以对字符串做一个遍历,如果是({【,的话,就让对应的}】)入栈,如果不是,说明已经遍历到右半边了
此时,直接比较栈顶元素和遍历到的元素是否相等,不相等则报错
本题中不匹配的类型有三种:
- 左边多了
- 右边多了
- 数量一样但是有不匹配
3对应的结果是遍历过程中不相等,1和2 对应的结果是遍历结束之后栈没有空或者遍历过程中栈就空了
var isValid = function(s) {
const stack = [];
map = {
'(' : ')',
'[' : ']',
'{' : '}',
}
for(const x of s) {
if(x in map) {
stack.push(x);
continue;
};
if(map[stack.pop()] !== x) return false;
}
return !stack.length;
};
总结
这里用了map,以及对象的存在性测试in,使得代码方便了很多
对于JS来说,栈结构是用数组结构实现的
所以,如果情况2,遍历过程中栈就空了
stack.pop()的结果是undefined
一样的不等于x,直接return false
1047. 删除字符串中的所有相邻重复项
题目链接:1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
第一想法
遍历字符串,将字符串存入栈内
比较当前字母与栈顶元素
如果相等,则栈顶元素出栈
否则,当前字母入栈
遍历结束后返回栈内元素组成的字符串
思路
var removeDuplicates = function(s) {
const stack = [];
for(const x of s) {
// 用来存储栈顶元素
let c = null;
// 如果相等,则出栈
if(stack.length && x === (c = stack.pop())) continue;
// 不相等,把出栈的元素再放回去
c && stack.push(c);
// 把字符串中字母放进去
stack.push(x);
}
// 返回字符串
return stack.join("");
};
总结
这一题本来想用栈的方法:
peek() 返回栈顶的元素,不对栈做任何修改
但是JS中栈是用数组实现
这里又没有对栈做什么封装
所以实际上这里的stack还是一个数组
就只能pop,push了
不过代码中逻辑用的挺巧妙,可以好好记住一下
150. 逆波兰表达式求值
题目链接:150. 逆波兰表达式求值 - 力扣(LeetCode)
第一想法
用栈来实现
运算对象依次入栈,当运算符入栈时,前两个元素出栈,并且运算,将结果入栈
继续重复上面的操作
思路
var evalRPN = function(tokens) {
let stack = [];
for(let i = 0; i < tokens.length; i++){
if(tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '/' || tokens[i] == '*'){
let num1 = stack.pop();
let num2 = stack.pop();
if(tokens[i] == '+'){
stack.push(num1 + num2);
}
if(tokens[i] == '-'){
stack.push(num2 - num1);
}if(tokens[i] == '/'){
stack.push(parseInt(num2/num1));
}
if(tokens[i] == '*'){
stack.push(num1 * num2);
}
}else{
stack.push(Number(tokens[i]));
}
}
return stack[0];
};
总结
这里主要是要注意,数字入栈时要转换一下,从字符串转换为数字类型
以及,减和除的情况下
是num1 - num2 还是 num2 - num1
这里比较容易犯错