逆波兰表达式求值题解

此篇参考: https://www.cnblogs.com/lulipro/p/7450886.html

逆波兰算法

逆波兰算法的核心思想是将普通的中缀表达式转换为后缀表达式。
中缀表达式:例如 2 + 3 ,我们最熟悉的算术表达式就是中缀表达式。
后缀表达式:方便计算机处理的表达式,如 2 3 +。
我们熟悉的算术表达式一般由操作数(数字)、分界符(括号)、运算符(加减乘除)组成。

逆波兰算法原理

求解这一类的算法题核心步骤有两个:

  • 将中缀表达式转换为后缀表达式
  • 对后缀表达式求值

1、将中缀表达式转换为后缀表达式

  • 开始操作前需要初始化两个栈,s1和s2,s1用来存储运算符和分界符,s2用来存储后缀表达式
  • 接着就遍历原始表达式中的每一个元素
    • 遍历的是数字,直接存储到后缀表达式(即s2)
    • 遍历的是分界符
      • 如果是左括号,直接压入栈s1中
      • 如果是右括号,则丢弃右括号,并且循环弹出栈中元素,放入s2中,直到遇到左括号停止。左括号也要丢弃。
    • 遍历的是运算符
      • 如果栈s1中为空,或者s1的栈顶是左括号,或者s1的栈顶的运算符的优先级小于当前的运算符,都直接将运算符压入栈s1
      • 如果s1的栈顶的运算符的优先级大于或等于当前的运算符,需要将栈顶元素弹出压入栈s2。确保s1栈顶的运算符优先级小于当前运算符,再将当前运算符压入栈s1。
  • 最后如果s1中还有元素,依次弹出并压入s2

2、对后缀表达式求值

  • 对后缀表达式遍历
    • 如果是数字,直接压入栈s1中
    • 如果是运算符, 从栈中弹出两个数, num1和num2,使用运算符对num1和num2计算。计算结果需要压入栈中
  • 遍历结束,栈中的数就是最后的结果

题解

150. 逆波兰表达式求值(力扣)
剑指 Offer II 036. 后缀表达式

这两题直接给出了后缀表达式,因此直接计算即可

var evalRPN = function(tokens) {
  let stack = []
  for (let i of tokens) {
    if (!Number.parseInt(i) && i !== '0') {
      const num1 = Number.parseInt(stack.pop())
      const num2 = Number.parseInt(stack.pop())
      let temp = null
      if (i === '+') {
        temp = num2 + num1
      } else if (i === '-') {
        temp = num2 - num1
      } else if (i === '*') {
        temp = num2 * num1
      } else if (i === '/') {
        temp = num2 / num1
        temp = temp > 0 ? Math.floor(temp) : Math.ceil(temp)
      }
      stack.push(temp)
    }else{
      stack.push(i)
    }
  }
  return Number.parseInt(stack.pop())
};

NC137 表达式求值(牛客题霸)

此题需要先计算后缀表达式,再用后缀表达式计算结果

function solve(s) {
  // 维护一个运算符优先级
  let map = new Map()
  map.set('-', 0)
  map.set('+', 0)
  map.set('*', 1)
  // 中缀表达式转后缀表达式
  let stack = []
  let l = []
  let tempNum = ''
  for (let i of s) {
    // 数字
    if (i >= '0' && i <= '9') {
      tempNum += i
      // 分界符
    } else if (i == '(' || i == ')') {
      if (tempNum != '') {
        l.push(tempNum)
        tempNum = ''
      }
      if (i == '(') {
        stack.push(i)
      } else {
        let temp = stack.pop()
        while (temp !== '(') {
          l.push(temp)
          temp = stack.pop()
        }
      }
      // 运算符
    } else {
      if (tempNum != '') {
        l.push(tempNum)
        tempNum = ''
      }
      if (!stack || stack[stack.length - 1] == '(' || map.get(stack[stack.length - 1]) < map.get(i)) {
        stack.push(i)
      } else {
        while (stack.length && map.get(stack[stack.length - 1]) >= map.get(i)) {
          l.push(stack.pop())
        }
        stack.push(i)
      }
    }
  }
  if (tempNum != '') {
    l.push(tempNum)
    tempNum = ''
  }
  while (stack.length) {
    l.push(stack.pop())
  }
  // 后缀表达式求值
  for (let i of l) {
    if (i <= '9' && i >= '0') {
      stack.push(i)
    } else {
      const num1 = Number.parseInt(stack.pop())
      const num2 = Number.parseInt(stack.pop())
      let temp = null
      if (i == '*') {
        temp = num2 * num1
      } else if (i == '-') {
        temp = num2 - num1
      } else if (i == '+') {
        temp = num2 + num1
      }
      if (temp) {
        stack.push(temp)
      }
    }
  }
  return Number.parseInt(stack.pop())
}

你可能感兴趣的:(算法,算法,stack,javascript)