代码随想录算法训练营第十一天|栈和队列 part2

68 阅读3分钟

20. 有效的括号

题目链接:20. 有效的括号 - 力扣(LeetCode)

第一想法

没啥想法

想了想双指针和哈希表map,感觉都太复杂了

思路

栈非常适合做对称匹配类型的题目

image-20230325131134591

这道题可以对字符串做一个遍历,如果是({【,的话,就让对应的}】)入栈,如果不是,说明已经遍历到右半边了

此时,直接比较栈顶元素和遍历到的元素是否相等,不相等则报错

本题中不匹配的类型有三种:

  • 左边多了
  • 右边多了
  • 数量一样但是有不匹配

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

这里比较容易犯错