772. 基本计算器 III
题设¶
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,乘号 *,除号 /,非负整数和空格 。
输入: "1 + 1"
输出: 2
输入: "(1+(4+5+2)-3)+(6+8)"
输出: 23
输入: "2*(5+5*2)/3+(6/2+8)"
输出: 21
步骤一:仅加法¶
/**
* @param {string} s
* @return {number}
*/
var calculate = function(s) {
const queue = [];
for(let i = 0; i < s.length; i++) {
queue.push(s[i])
}
queue.push('+'); // 处理最后一次加法
let num = 0, sum = 0;
while (queue.length > 0) {
const c = queue.shift();
if (/\d/.test(c)) {
num = num * 10 + Number(c);
} else {
sum += num;
num = 0;
}
}
return sum;
};
步骤二:支持减法¶
- 加入 sign 标志当前 num 符号
/**
* @param {string} s
* @return {number}
*/
var calculate = function(s) {
const queue = [];
for(let i = 0; i < s.length; i++) {
if (s[i] !== ' ') { // 过滤空格
queue.push(s[i])
}
}
queue.push('+'); // 处理最后一次加法
let num = 0, sum = 0;
let sign = '+'; // 当前 num 符号标志变量
while (queue.length > 0) {
const c = queue.shift();
if (/\d/.test(c)) {
num = num * 10 + Number(c);
} else {
if (sign === '-') {
sum -= num;
} else if (sign === '+'){
sum += num;
}
num = 0;
sign = c;
}
}
return sum;
};
步骤三:支持乘法和除法¶
- 考虑符号优先级
- 堆栈缓存高优先级计算结果
var calculate = function(s) {
const queue = [];
for(let i = 0; i < s.length; i++) {
if (s[i] !== ' ') { // 过滤空格
queue.push(s[i])
}
}
queue.push('+'); // 处理最后一次加法
let num = 0;
let sign = '+'; // 当前 num 符号标志变量
let stack = [];
while (queue.length > 0) {
const c = queue.shift();
if (/\d/.test(c)) {
num = num * 10 + Number(c);
} else {
if (sign === '+') {
stack.push(num);
} else if (sign === '-'){
stack.push(-num);
} else if (sign === '*') {
stack.push(stack.pop() * num);
} else if (sign === '/') {
stack.push(stack.pop() / num);
}
num = 0;
sign = c;
}
}
let sum = 0;
for(let i = 0; i < stack.length; i++) {
sum += stack[i];
}
return sum;
};
步骤四:支持小括号¶
- 递归计算括号内表达式
- 遇到左括号
(
时,开始递归计算括号内表达式 - 遇到右括号
)
时,表明小括号计算结束,结束循环,返回当前总和
var calculate = function(s) {
const queue = [];
for(let i = 0; i < s.length; i++) {
if (s[i] !== ' ') { // 过滤空格
queue.push(s[i])
}
}
queue.push('+'); // 处理最后一次加法
return _calculate(queue);
};
var _calculate = function(queue) {
let sign = '+'; // 当前 num 符号标志变量
let num = 0;
let stack = [];
while (queue.length > 0) {
const c = queue.shift();
if (/\d/.test(c)) {
num = num * 10 + Number(c);
} else if (c === '(') {
// 遇到小括号,开始递归计算号内表达式,将计算结果赋给当前 num
num = _calculate(queue);
} else {
if (sign === '+') {
stack.push(num);
} else if (sign === '-'){
stack.push(-num);
} else if (sign === '*') {
stack.push(stack.pop() * num);
} else if (sign === '/') {
stack.push(stack.pop() / num);
}
num = 0;
sign = c;
// 遇到右括号退出循环,返回当前计算总和
if (c === ')') {
break;
}
}
}
let sum = 0;
for(let i = 0; i < stack.length; i++) {
sum += stack[i];
}
return sum;
};