这道题还是栈的使用。
思路:
- 遇到
+
、-
、*
、/
,先缓存这些运算符 - 如果不是运算符,则收集字符串
- 根据当前的运算符以及数字
+
:将字符串转成数字压入栈中-
:将字符串转成数字,并取负,压入栈中*
:将栈顶元素弹出,与当前字符做乘法,结果再入栈/
:将栈顶元素弹出- 如果栈顶元素为负数,取正与字符做除法之后再去负,压入栈中
- 如果栈顶元素为正数,直接与字符做除法,结果入栈
- 扫描完数组之后,遍历栈(
javascript
中的数组)完成对所有元素的求和。
这里的第三步,对栈顶元素判断正负,是因为负数向下取整与正数向下正取之后的数字部分会相差1
。比如 -3 / 2
,向下取整之后是-2
,而正数3 / 2
向下取整是1
。这道题中的负数是因为正数的-
运算转成了负数的+
运算,这样做的好处是避免在stack
中存储运算符,从而避免在弹出时还要对栈顶元素是否是+ -
运算符的判断。
function calculate(s: string): number {
const stack: number[] = []
const len = s.length
let i = 0
// 第一位是非负整数
let op = '+'
while (i < len) {
if (['+', '-', '*', '/'].indexOf(s[i]) > -1) {
op = s[i]
i++
} else {
let num = ''
// 收集数字,可以是多位数
while (i < len && ['+', '-', '*', '/'].indexOf(s[i]) === -1) {
num += s[i]
i++
}
switch (op) {
case '-':
stack.push(-num)
break
case '+':
stack.push(+num)
break
case '*':
stack.push(stack.pop() as number * +num)
break
case '/':
const top = stack.pop() as number
stack.push(
top < 0 ? -Math.floor(-top / +num) : Math.floor(top / +num)
)
break
}
}
}
// 计算总和
return stack.reduce((calc, cur) => {
return (calc += cur)
}, 0)
}