栈与队列:20. 有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

提示:努力生活,开心、快乐的一天


20. 有效的括号

题目链接:20. 有效的括号

💡解题思路

  • 数量要匹配、类型要匹配、顺序要匹配
  • 借助map去定义需要遍历的数组的类型

🤔遇到的问题

  • 判断右侧符号时,出错了

💻代码实现

栈+map

var isValid = function(s) {
  //如果字符串是奇数,字符串肯定无效
  if(s.length%2!==0) return false
  let stack =[];
  const map ={
      '(':')',
      '[':']',
      '{':'}'
  }
  for(let i of s){
     //判断左侧符号
      if(i in map){
        //将左侧存放到栈中
          stack.push(i)
          continue
      }
      //判断右侧符号  
      if(map[stack.pop()]!=i) return false
  }
  //是否为空
  return !stack.length
};

🎯题目总结

有三种不匹配的情况

  • 字符串里左方向的括号多余了 ,所以不匹配在这里插入图片描述

  • 括号没有多余,但是 括号的类型没有匹配上 在这里插入图片描述

  • 字符串里右方向的括号多余了,所以不匹配 在这里插入图片描述


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

题目链接:1047. 删除字符串中的所有相邻重复项

💡解题思路

  1. 遍历字符串,将 遍历的元素与栈顶元素相比较,与栈顶元素相同,则栈顶元素弹出,与栈顶元素不同,则存入栈中 ,最终栈中的元素就是最终的
  2. 数组模拟栈 进行实现
  3. 双指针模拟栈 进行实现

🤔遇到的问题

  1. 数组模拟栈时,遍历元素需要与数组元素作比较时出错
  2. 双指针模拟时 ,将遍历数组存入栈中时 ,指针指向错误

💻代码实现

数组模拟栈

var removeDuplicates = function(s) {
  //先进的项在最前面
  let result = []
  for(let i=0;i<s.length;i++){
    //如果遍历的元素与数组最后一个元素不同
      if(s[i]===result[result.length-1]){
        //从尾部删除一个
          result.pop()
      }else{
        //在尾部添加一个
          result.push(s[i])
      }
  }
  return result.join('')
};

双指针模拟栈

var removeDuplicates = function(s) {
  let sArr = Array.from(s)
  // 指向栈顶元素的下标
  let top = -1
  for(let i=0;i<sArr.length;i++){
    // top === -1 即空栈||当前遍历的元素与栈顶元素不相等
      if(top === -1||sArr[top]!==sArr[i]){
        //必须top先加1,再 赋值 
          top++
          sArr[top] = sArr[i]    
      }else{
        //当前遍历的元素与栈顶元素相等
          top--
      }
  }
  // 栈顶元素下标 + 1 为栈的长度
  sArr.length = top+1
  return sArr.join('')
};

🎯题目总结

无论那种解法, 用栈来存放,那么栈的目的,就是存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素


150. 逆波兰表达式求值

题目链接:150. 逆波兰表达式求值

💡解题思路

  1. 什么是逆波兰表达式?
    逆波兰表达式:是一种后缀表达式,所谓后缀就是指运算符写在后面
    平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
    该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
    2.使用栈解决改题: 遇到数字则入栈;遇到运算符则取出栈顶两个数字进行计算,并将结果压入栈中

🤔遇到的问题

  1. 数字入栈未 转化为Number类型
  2. 取栈顶两个元素时,顺序不对

💻代码实现

var evalRPN = function(tokens) {
  const stack = []
  for(let num of tokens){
    //判断是否为运算符
      if(isNaN(Number(num))){
        //取栈顶两个元素,选取N2,再取N1,这对于减法与除法 很重要
          let n2 = stack.pop()
          let n1 = stack.pop()
          //运算结果再入栈
          switch(num){
              case '+':
              stack.push(n1+n2)
              break;
              case '-':
              stack.push(n1-n2)
              break;
              case '*':
              stack.push(n1*n2)
              break;
              case '/':
              stack.push(n1/n2|0)
              break
          }
      }else{
        //非运算符直接入栈,转化为Number类型,此时为String类型
          stack.push(Number(num))
      }
  }
  //最后留在栈中的值就是最终的结果
  return stack[0]
};

🎯题目总结

其实逆波兰表达式相当于是 二叉树中的后序遍历
后缀表达式对计算机来说是非常友好的
在1970年代和1980年代,惠普在其所有台式和手持式计算器中都使用了RPN(后缀表达式),直到2020年代仍在某些模型中使用了RPN

🎈今日心得

栈的题 ,万变不离其宗 ,感觉做的题多了就越来越顺手了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值