开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情
给你一个字符串表达式 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 * 105s由数字、'+'、'-'、'('、')'、和' '组成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;
};