# 224. 基本计算器

# 解题思路

  • 将字符串拆分成数字和运算符组成的数组
  • 遍历数组,消除括号
    • 遇到左括号则创建一个新的数组,并将当前数组入栈
    • 遇到数字和运算符则将其添加到栈顶数组中
    • 遇到右括号则计算出栈顶数组内所有数字的运算结果,然后将处理后的数组出栈,同时将结果添加到新的栈顶数组中
  • 遍历结束,栈内只有一个元素(此时已经去除了所有的括号),所以计算其结果即为最终结果
var calculateCore = function (strArr) {
  let result = 0
  let prevOp = '+'

  for (let i = 0; i < strArr.length; i++) {
    const item = strArr[i]

    switch (item) {
      case '+':
      case '-':
        prevOp = item
        break
      default:
        result = handleCalculate(result, prevOp, item)
        break
    }
  }

  return result

  function handleCalculate(val1, op, val2) {
    switch (op) {
      case '+':
        return parseFloat(val1) + parseFloat(val2)
      case '-':
        return parseFloat(val1) - parseFloat(val2)
      default:
        throw new Error('unknown op.')
    }
  }
}

function splitStringByNonNumber(str) {
  const regex = /(\d+)|[^\d\s]/g
  const result = str.match(regex).filter(Boolean)

  return result
}

var calculate = function (s) {
  const strArr = splitStringByNonNumber(s)

  if (strArr.length === 1) return parseFloat(strArr[0])

  const pendingStack = [[]]
  let currentLevel = 0

  for (let i = 0; i < strArr.length; i++) {
    const item = strArr[i]

    switch (item) {
      case '(':
        pendingStack.push([])
        currentLevel++
        break
      case ')':
        currentLevel--
        pendingStack[currentLevel].push(calculateCore(pendingStack.pop()))
        break
      default:
        pendingStack[currentLevel].push(item)
        break
    }
  }

  return calculateCore(pendingStack[0])
}

在 LintCode 中提供了一种括号展开 + 栈的解题方式,详情可点击查看题解 (opens new window)

# 参考