前端算法Hot100-栈与队列系列(JS)

3 阅读3分钟

20. 有效的括号

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

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 注意空字符串可被认为是有效字符串。

示例 1:

  • 输入: "()"
  • 输出: true

示例 2:

  • 输入: "()[]{}"
  • 输出: true

示例 3:

  • 输入: "(]"
  • 输出: false

核心:用「栈」的先进后出特性,匹配成对括号

  1. 准备一个空栈,专门存待匹配的右括号

  2. 遍历字符串:

    • 碰到左括号 ( [ {,就把对应的右括号压进栈
    • 碰到右括号,就弹出栈顶的括号对比,不匹配直接判定无效
  3. 遍历结束后,栈为空 就是有效括号,否则无效

var isValid = function(s) {
  let 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;
}

155. 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

思路

  • 两个栈:一个正常存数据,一个专门存最小值。

  • 入栈时,新数字小于等于最小栈栈顶,就同时进最小栈,保证栈顶始终最小。

  • 出栈时,如果弹出的是当前最小值,最小栈也同步弹出。

  • 获取最小值直接取最小栈栈顶,不用遍历,速度最快。

//最小栈
var MinStack = function() {
  this.stack = []; // 单栈:存差值
  this.min = 0;    // 仅一个变量存最小值
};

MinStack.prototype.push=function(val){
  this.stack.push(val)
  if(this.stack.length===0|| val<= this.MinStack[this.MinStack.length-1]){
    this.MinStack.push(val)
  }
}

MinStack.prototype.pop=function(){
 let topVal= this.stack.pop(val)
  if(topVal===this.MinStack[this.MinStack.length - 1]){
    this.MinStack.pop()
  }
}

MinStack.prototype.top = function () {
  // 直接返回主栈的最后一个元素(栈顶)
  return this.stack[this.stack.length - 1 ];
};

MinStack.prototype.getMin = function () {
  // 最小栈的栈顶,永远是当前最小值
  // 直接拿,不用遍历!!!
  return this.minStack[this.minStack.length - 1]
};

394. 字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。

编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。

此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。

示例 1:

输入: s = "3[a]2[bc]"
输出: "aaabcbc"

典型解法:单调栈,时间复杂度 O (n)。

var decodeString = function(s) {
   const stack = [];
   let currentStr = '';
    // 当前累计的数字(处理多位数)
    let currentNum = 0;
    for(let i = 0; i < s.length; i++){
        const char = s[i];
        if(char >= '0' && char <= '9'){
          currentNum=currentNum*10+Number(char)
        }
        else if(char==='['){
          stack.push[currentStr,currentNum]
          let currentStr=''
          let currentNum =0
        }
        else if(char===']'){
          let [prevStr,num] =stack.pop()
          currentStr= prevStr + currentStr.repeat(num);
        }
        else {
          currentStr = currentStr+char
        }
    }
    return currentStr
}

739. 每日温度

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。

  • 用栈保存下标,保证栈里对应的温度单调递减

  • 遍历每一天:

    1. 如果当前温度 > 栈顶温度,说明栈顶那天找到了更暖和的一天
    2. 弹出栈顶,计算天数差
    3. 重复直到栈空或栈顶温度更大
    4. 把当前下标压入栈 示例 1:
输入: temperatures = [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
var dailyTemperatures = function(temperatures) {
  const n = temperatures.length;
    const res = new Array(n).fill(0);
    const stack = [];
    for (let i = 0; i < n; i++) {
     while(stack.length && temperatures[i] > temperatures[stack[stack.length - 1]]){
      let topIndex = stack.pop();   // 弹出栈顶那天的下标
      res[topIndex] = i - topIndex; // 天数差就是答案
     }
     stack.push(i);
    }
    return res;
}