基本计算器

131 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

224. 基本计算器 - 力扣(LeetCode)

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()

示例 1:

输入: s = "1 + 1"
输出: 2

示例 2:

输入: s = " 2-1 + 2 "
输出: 3

示例 3:

输入: s = "(1+(4+5+2)-3)+(6+8)"
输出: 23

提示:

  • 1 <= s.length <= 3 * 105
  • s 由数字、'+''-''('')'、和 ' ' 组成
  • s 表示一个有效的表达式
  • '+' 不能用作一元运算(例如, "+1" 和 "+(2 + 3)" 无效)
  • '-' 可以用作一元运算(即 "-1" 和 "-(2 + 3)" 是有效的)
  • 输入中不存在两个连续的操作符
  • 每个数字和运行的计算将适合于一个有符号的32位整数

思路

由于运算符只有+-,不存在运算符之间优先级问题,可以使用展开括号+栈的方法求解。先来看展开括号,由学过的数学知识可知,展开括号后,括号内的运算符和括号前的运算符有关:

  • 当括号前是+时,括号内运算符不变,直接去括号
  • 当括号前是-时,括号内运算符取反,再去括号

当括号存在嵌套时,我们就需要使用栈来保存当前的运算符,当遇到(时入栈,遇到)时出栈。

解题

/**
 * @param {string} s
 * @return {number}
 */
var calculate = function (s) {
  const stack = [];
  const zero = "0".charCodeAt(0);
  const n = s.length;
  let prevSign = true;
  let sign = true;
  let sum = 0;
  let i = 0;
  while (i < n) {
    const char = s[i];
    i++;
    if (char === " ") {
      continue;
    } else if (char === "+") {
      sign = prevSign;
    } else if (char === "-") {
      sign = !prevSign;
    } else if (char === "(") {
      stack.push(prevSign);
      prevSign = sign;
    } else if (char === ")") {
      prevSign = stack.pop();
    } else {
      let num = char.charCodeAt(0) - zero;
      while (true) {
        let code = s.charCodeAt(i) - zero;
        if (code >= 0 && code <= 9) {
          num = num * 10 + code;
          i++;
        } else {
          break;
        }
      }
      sum += sign ? num : -num;
    }
  }
  return sum;
};