[JavaScript 刷题] 栈 - 基础计算器 II, leetcode 227

Posted GoldenaArcher

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaScript 刷题] 栈 - 基础计算器 II, leetcode 227相关的知识,希望对你有一定的参考价值。

[javascript 刷题] 栈 - 基础计算器 II, leetcode 227

github repo 地址: https://github.com/GoldenaArcher/js_leetcode,Github 的目录 大概 会更新的更勤快一些。

题目地址:227. Basic Calculator II

题目

如下:

Given a string s which represents an expression, evaluate this expression and return its value.

The integer division should truncate toward zero.

You may assume that the given expression is always valid. All intermediate results will be in the range of [-2^^31, 2^(31 - 1)].

Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().

解题思路

基本上还是用栈的思路去解决,遇到 +- 就直接推到栈中,遇到 */ 就从栈中弹出处理。

顺便,这道题反而是计算器系列中最简单的,优先做这一题找点思路比较好。

除此之外有两点需要注意的:

  1. 不能仅使用 Math.floor(),在负数的情况下需要使用 Math.ceil()。否则可以用 Math.trunc() 代替
  2. 如果使用 s[i] >= 0 && s[i] <= 9 需要注意隐式转型的问题。' ' >= 0 && ' ' <= 9 的结果是 true,就是因为隐式转型会将 ' ' 转化成 0.

除了使用 stack——空间复杂度为 O ( n ) O(n) O(n)——之外,这道题还有一种空间复杂度为 O ( 1 ) O(1) O(1) 解法。其方法是保存之前计算的数字,如果是 +- 的话就继续计算过程,如果是 */ 的话就先还原之前计算的数字,处理完优先级较高的数字再放进去。这种算法需要额外保存的变量有:

  • 总和 sum
  • 之前计算的数字 prev
  • 现在计算的数字 curr
  • 现在需要使用的运算符 currOperator

"14-3/2" 为例,初始化所有的数字都为 0,运算符则为 +,每次获取一次数字就进行一次计算。

  1. 在获取到一个数字 14 后,判断之前的运算符为 +,因此这里进行 0 + 14 的计算,将 prev 更新为 14

  2. 更新运算符为 -

  3. 在获取到第二个数字 3 时,进行 14 - 3 的操作,sum 更新为 11,将 prev 更新为 -3

  4. 更新运算符为 /

  5. 获取第三个数字 2,因为 / 的优先级较高,因此需要移除上一个计算过的数字,即进行 11 - -3 的操作,随后进行 -3 / 2 的操作,再将值加入 sum 中。

使用 JavaScript 解题

解法 1,stack

/**
 * @param string s
 * @return number
 */
var calculate = function (s) 
  const stack = [];

  for (let i = 0; i < s.length; i++) 
    if (s[i] === " ") continue;

    if (/[0-9]/.test(s[i])) 
      let num = +s[i++];
      while (/[0-9]/.test(s[i])) num = num * 10 + +s[i++];
      i--;
      if (stack[stack.length - 1] === "*") 
        stack.pop();
        const left = stack.pop();
        stack.push(left * num);
       else if (stack[stack.length - 1] === "/") 
        stack.pop();
        const left = stack.pop();
        stack.push(Math.trunc(left / num));
       else stack.push(num);

      continue;
    

    stack.push(s[i]);
  

  let left = +stack[0];
  for (let i = 1; i < stack.length; i++) 
    if (stack[i] === "+") 
      left += +stack[++i];
     else if (stack[i] === "-") 
      left -= stack[++i];
    
  

  return left;
;

解法 2

遇到减号就将 prev 更新为负数。

/**
 * @param string s
 * @return number
 */
var calculate = function (s) 
  let sum = 0,
    prev = (curr = 0),
    currOperator = "+";

  for (let i = 0; i < s.length; i++) 
    if (s[i] === " ") continue;

    if (/[0-9]/.test(s[i])) 
      curr = s[i++];
      while (/[0-9]/.test(s[i])) curr = curr * 10 + +s[i++];
      i--;

      if (currOperator === "+") 
        sum += +curr;
        prev = curr;
       else if (currOperator === "-") 
        sum -= curr;
        prev = -curr;
       else if (currOperator === "*") 
        sum -= prev;
        sum += prev * curr;
        prev = prev * curr;
       else if (currOperator === "/") 
        sum -= prev;
        sum += +Math.trunc(prev / curr);
        prev = Math.trunc(prev / curr);
      
     else 
      currOperator = s[i];
    
  

  return sum;
;

以上是关于[JavaScript 刷题] 栈 - 基础计算器 II, leetcode 227的主要内容,如果未能解决你的问题,请参考以下文章

[JavaScript 刷题] 栈 - 最小栈, leetcode 155

[JavaScript 刷题] 栈 - 最小栈, leetcode 155

[JavaScript 刷题] 栈 - 原子的数量, leetcode 726

[JavaScript 刷题] 栈 - 原子的数量, leetcode 726

[JavaScript 刷题] 栈 - 原子的数量, leetcode 726

[JavaScript 刷题] 栈 - 有效的括号, leetcode 20