代码随想录算法训练营第十一天|20. 有效的括号 、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值「栈与队列」

130 阅读5分钟

20. 有效的括号

题目

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。 有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
思路
  1. 把字符串转换为一个字符数组
  2. 设置一个栈结构用来对括号进行判断
  3. 分别设置两个数组,里面分别装了左右三种小括号,方便后面进行匹配
  4. 设置一个循环,次数为字符数组的长度
    1. 获取当前元素,判断是否是左括号,如果是就放进栈中
    2. 判断是否是右括号,如果是就判断当前栈是否为空,如果为空就返回false,或者把栈顶元素取出和右括号用下标值比对匹配,不匹配就返回false
  5. 最后判断栈是否为空,不为空返回false,为空返回true
代码
/**
 * @param {string} s
 * @return {boolean}
 */
var isValid = function(s) {
    const bracket = s.split('')
    const box = []
    const left = ['(','[','{']
    const right = [')',']','}']
    for (let i =0;i<bracket.length;i++) {
        if (left.includes(bracket[i])) {
            box.push(bracket[i])
            continue
        }
        if (right.includes(bracket[i])) {
            if (!box.length||left.indexOf(box.pop())!==right.indexOf(bracket[i])){
                return false
            }
        }
    }
    return box.length?false:true
};

优化:

优化的代码思路非常屌,就是直接对字符串遍历,获取每一个字符,如果是左括号中的一种,就把对应的右括号放在栈里,如果是右括号的一种,就直接从栈顶取元素,判断是否一样,如果不一样就返回false 最后判断栈长度,如果不为空就返回false,否则返回true。 还有一种思路,先声明一个表,键名是左括号,键值是对应的右括号,然后遍历字符串,如果当前元素是左括号,那就放入栈中,如果当前元素不是左括号,就把栈中元素取出来作为键名获取表中的键值和当前元素匹配,如果不匹配返回false,最后判断栈是否为空,为空返回true,否则返回false

代码
var isValid = function (s) {
  const stack = [];
  for (let i = 0; i < s.length; i++) {
    let c = s[i];
    switch (c) {
      case '(':
        stack.push(')');
        break;
      case '[':
        stack.push(']');
        break;
      case '{':
        stack.push('}');
        break;
      default:
        if (c !== stack.pop()) {
          return false;
        }
    }
  }
  return stack.length === 0;
};
// 简化版本
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;
};

总结:

括号匹配问题是一道非常经典的栈结构问题

1047. 删除字符串中的所有相邻重复项

题目

给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。 在 S 上反复执行重复项删除操作,直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

思路

设置一个栈结构,设置一个循环遍历字符串中的字符,判断如果栈为空,就直接把当前字符推入栈中,如果栈不为空,就把栈顶元素取出来和当前字符进行比较,如果不一样,再把当前字符推入栈中,否则弹出栈顶元素,最后返回栈转换的字符串。 写完之后感觉在对栈顶元素比较的这一步应该是做的复杂了。

代码

/**
 * @param {string} s
 * @return {string}
 */
var removeDuplicates = function(s) {
    const myStack = []
    for (let i = 0; i<s.length;i++) {
        if (myStack.length) {
            if (myStack[myStack.length-1] !== s[i]) {
                myStack.push(s[i])
            }else myStack.pop()
        }else myStack.push(s[i])
    }
    return myStack.join('')
};

优化:

可以用双指针模拟栈的方法。

总结:

比较简单的一个栈结构的题。

150. 逆波兰表达式求值

题目

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

思路

对数组进行遍历,如果当前元素是运算符,就连续两次取出栈顶元素,第一次取出的元素是右侧被运算的元素,第二次取出的元素是运算符左侧的元素,然后判断运算符进行对应的计算,得出结果后推入栈中,如果当前元素不是运算符就直接推入栈中,最后返回栈顶元素。 注意:因为数组中的元素以字符形式保存,所以要做一个隐式转换,转换为数字型;因为所有除法操作要向零截取,所以除法得到的结果要parseInt转换为整数。

代码

/**
 * @param {string[]} tokens
 * @return {number}
 */
var evalRPN = function(tokens) {
    const operater = ['+','-','*','/'],stack = []
    for (let i = 0;i<tokens.length;i++) {
        if (operater.includes(tokens[i])) {
            const right = stack.pop()
            const left = stack.pop()
            let tmp
            switch(tokens[i]) {
                case '+':
                tmp = +left + +right;
                break;
                case '-':
                tmp = left - right;
                break;
                case '*':
                tmp = left * right;
                break;
                case '/':
                tmp = parseInt(left / right);
                break;
            }
            stack.push(tmp)
        }else stack.push(tokens[i])
            console.log(stack)
    }
    return stack.pop()
};

优化:

看了代码随想录和我写的差不多。

总结:

考察栈的应用,比较简单。

Day11总结

今天栈的题目,做起来感觉比较简单,可能是因为自己比较熟悉,也可能是因为今天的题比较简单,期待队列的应用。