/** * https://leetcode.cn/problems/basic-calculator/?envType=study-plan-v2&envId=top-interview-150 * @param {string} s * @return {number} */ const calculate = function (s) { }; /* 定义一个sign变量,表示数前面的符号,当数字收集完毕就使用这个符号操作,这个变量的默认值为+1,原因很简单, 表达式为一个整体,可以理解为一个括号,这个括号之前隐式的包含了一个+号,比如表达式 -1 + 2 -(1-2),可以 把它看成+(-1 + 2 -(1-2)),我们还需要使用一个栈结构来保存每一层括号表示的符号,以上面的表达式为例,第一个 括号显然为+,所以栈结构为[+1],之后这个括号下一级的数都会受它影响,比如括号里面的-1会变为1*-1,1*(+2)都 保持不变,当遇到"("时需要把这一层的符号压入栈中,栈结构为[+1,-1],第二级的括号里面的数都会受他影响,当遇到 )表示,这一层级的数都操作完必了,栈中无需保存这一层级的符号,直接弹出即可,这样一次遍历即可得到结果。 */ function f1(s) { const opt = [1];// 保存每一层括号的符号,初始表达式可以看成一个整体,所以默认值为[1] let sign = 1; // 收集数字之后,数字前面的符号 let ret = 0; // 计数求和的结果 const n = s.length; // 字符串的长度,用于控制遍历 let i = 0; // 遍历下标 while (i < n) { if (s[i] === ' ') { // 遇到空格直接跳过 i++; } else if (s[i] === '+') { // 如果遇到加号,根据当前层级的符号更新sign sign = opt[opt.length - 1]; i++; } else if (s[i] === '-') { // 如果遇到减号,和上面同理 sign = -opt[opt.length - 1]; i++; } else if (s[i] === '(') { // 遇到左括号,表明层级加深,把sign压入栈中即可 opt.push(sign); i++; } else if (s[i] === ')') { // 遇到右括号,表明当前层级处理完毕,把当前层级的符号弹出即可 opt.pop(); i++; } else { // 上面的情况处理完毕,在这里只有一种情况,那么就是数字本身,数字可能是多位数,所以 // 需要一次遍历来收集 let num = 0; // 用于收集数字 while (i < n && s[i] >= '0' && s[i] <= '9') { num = num * 10 + (s[i] - '0'); i++; } // 数字收集完毕,通过它前面的符号sign和结果求和 ret += sign * num; } } return ret; }