Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
给你一个字符串表达式 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 * 105
- s 由数字、'+'、'-'、'('、')'、和 ' ' 组成
- s 表示一个有效的表达式
- '+' 不能用作一元运算(例如, "+1" 和 "+(2 + 3)" 无效)
- '-' 可以用作一元运算(即 "-1" 和 "-(2 + 3)" 是有效的)
- 输入中不存在两个连续的操作符`
- 每个数字和运行的计算将适合于一个有符号的 32位
整数
二、题解:
方法一 符号记录法
- 原理。使用字符串拼接数字,number转化类型,记录打开括号后所有的符号和数字即可。
- 思路。
- 使用replaceAll替换所有空格
- 使用字符串拼接数字,并判断是否是负数
- 遇到'('括号使用数组记录括号前的符号(正为1,负为-1),下一个符号需要依赖于数组最后一个的符号
- 遇到')'括号则数组退出一个
代码:
var calculate = function (s) {
if (Number(s) === parseInt(s)) {
return Number(s)
}
s = s.replaceAll(' ', '')
let i = 0;
let sum = 0
let stackChat = [1]
let tempStr = ''
while (i < s.length) {
if (s[i] === '' || s[i] === '+' || s[i] === '-') {
sum += Number(tempStr)
tempStr = ''
i++
} else if (s[i] === '(') {
if (i - 1 >= 0 && s[i - 1] === '+') {
stackChat.push(stackChat[stackChat.length - 1])
} else if (i - 1 >= 0 && s[i - 1] === '-') {
stackChat.push(-stackChat[stackChat.length - 1])
} else {
stackChat.push(1)
}
i++
} else if (s[i] === ')') {
stackChat.pop()
i++
} else {
if (stackChat.length>1) {
let lastNum = 1
if (i - 1 >= 0 && s[i - 1] === '-') {
lastNum = -1
}
let _stackChat = stackChat[stackChat.length - 1]
tempStr += (_stackChat * lastNum === -1 && !tempStr ? '-' : '') + s[i]
} else {
tempStr += (i - 1 >= 0 && s[i - 1] === '-' ? '-' : '') + s[i]
}
i++
}
}
sum += Number(tempStr)
return sum
};
方法二 符号变化法
- 原理。逐步进行,符号记录后转化为正确的符号,并使用循环叠加方式计算2位数以上的数字。
代码:
var calculate = function(s) {
if(Number(s) === parseInt(s)){
return Number(s)
}
let i = 0;
let ops = [1]
let sign = 1
let sum = 0
while (i < s.length) {
let item = s[i]
if (item === ' ') {
i++
} else if (item === '+') {
sign = ops[ops.length - 1]
i++
} else if (item === '-') {
sign = -ops[ops.length - 1]
i++
} else if (item === '(') {
ops.push(sign)
i++
} else if (item === ')') {
ops.pop()
i++
} else {
let num = 0
while (!isNaN(Number(s[i])) && i < s.length && s[i] !== ' ') {
num = num *10 + Number(s[i])
i++
}
sum+= sign*num
}
}
return sum
};
方案比较
方案一 时间复杂度O(N) 方案二 时间复杂度O(N),虽然是双循环,但是i共用,所以没有多余的时间开销
三、总结
- 此题可以符号记录法和符号变化法两种方案
- 逐步比较法主要是使用字符串拼接数字,number转化类型,记录打开括号后所有的符号和数字即可。
- 记录缺陷法逐步进行,符号记录后转化为正确的符号,并使用循环叠加方式计算2位数以上的数字。
文中如有错误,欢迎在评论区指正