LeetCode刷题,基本计算器II(227)

255 阅读1分钟

基本计算器II

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

整数除法仅保留整数部分。

解题代码

  1. 将表达式拆成两部分,一部分包含操作数,一部分包含运算符。
  2. 分别入栈,入栈运算符时判断当前优先级是否小于前面栈顶元素优先级,如果是,那么需要先处理完前面栈中运算符
var calculate = function(s) {
  let numStack = []; // 存储操作数
  let opsStack = []; // 存储运算符
  let num = 0; 
  s = s.replace(/\s/g,"").split(""); // 去除空格并拆分成数组
  s.push("@"); // 保证末尾有一个操作符可以进行递归循环判断计算
  for (let i = 0; i < s.length; i++) {
    const op = s[i];
    if (level(op) === 0) {
      num = num * 10 + Number(op); // 非个位数字进行累加,如 123 + 5 + 1 -> [1,2,3,+,5,+,1],遇到运算符时,才进行操作数入栈
      continue;
    }
    numStack.push(num); // 操作数入栈
    num = 0; // 前一个操作数入栈后,重置
    while (opsStack.length && level(op) <= level(opsStack[opsStack.length - 1])) { // 当前运算符优先级小于栈顶运算符优先级,进行计算
      const b = numStack.pop(); // 操作数栈依次出栈两个元素进行计算、例子 如 3 + 2 * 5 ->  nStack = [3,2,5] 
      const a = numStack.pop(); // 如计算 a * b ,此时 a b -> [2(a),5(b)];
      const op = opsStack.pop(); // oStack = [+,*,](未入栈当前操作符为@),弹出 * 
      numStack.push(calc(a, b, op)); // 计算结果,将结果重新压入操作数栈 = [3,10] ,此时 oStack = [+], 当前 @ 操作符依然小于,那么循环条件依然可以进行 res -> [13] oStack = [];
    }
    opsStack.push(op); // 处理完前面运算符优先级计算之后,压入当前运算符
  }
  return numStack.pop();
};

var level = function(op) {
  switch (op) {
    case "@": return -1;
    case "+": ;
    case "-": return 1; 
    case "*": ;
    case "/": return 2; 
  }
  return 0; 
}

var calc = function(a,b,op) {
  a = Number(a);
  b = Number(b);
  switch (op) {
    case "+": return a + b;
    case "-": return a - b; 
    case "*": return a * b;
    case "/": return a / b >> 0; // 保留整数
  }
  return 0
}