题目
LeetCode.224.基本计算器(困难)
给你一个字符串表达式 s
,请你实现一个基本计算器来计算并返回它的值。
提示:
-
1 <= s.length <= 3 * 105
-
s
由数字、'+'
、'-'
、'('
、')'
、和 ' '
组成
-
s
表示一个有效的表达式
题解
思路
- 表达式计算是从左到右遍历的,所以从左到右遍历字符串。
- 用result变量记录左边已经计算过的表达式的值。
- 新的表达式计算出来后,与result累加结果。
操作数识别
- 遇到连续数字,就做累加。
- 每遇到一个数字字符,把前面累加的结果乘以十,再加上当前数字值。
什么时候停止累加操作数?
遇到非数字字符操作数就可以确定了。
遇到的非数字字符可能会有:+
、-
、(
、)
。
运算符
- 只有加减运算,优先级相同。
- 可以把减法当作加法,识别完操作数,如果前面是减号,就当作负数。
- 用一个sign变量记录运算符,为1表示操作数前是加号,为-1表示操作数前是减号。
- 操作数识别完后,乘以sign,再与result累加。
括号
- 多括号时,优先计算最内层的括号。
- 遇到左括号时,左侧表达式需要等待括号内表达式计算得出结果才能继续计算,所以需要暂存左侧表达式之前累加的结果和运算符。
- 括号会有嵌套,需要保存每一层括号的临时计算结果,且是从左向右遍历的,访问临时计算结果又是从右到左,所以用栈存储。
- 遇到右括号时,需要从栈中取出之前临时状态继续运算。
题解1:暴力递归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class Solution { data class ExpResult(val value: Int, val endIndex: Int)
fun calculate(s: String): Int { val n = s.length
fun cal(i: Int): ExpResult { var result = 0 var operand = 0 var sign = 1 var j = i while (j < n) { val c = s[j] if (c in '0'..'9') { operand = operand * 10 + (c - '0') } else { result += sign * operand operand = 0 when (c) { '+' -> sign = 1 '-' -> sign = -1 '(' -> { val exp = cal(j + 1) result += sign * exp.value j = exp.endIndex } ')' -> return ExpResult(result, j) } } j++ } result += sign * operand return ExpResult(result, n - 1) }
return cal(0).value } }
|
题解2:基于迭代的栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| import java.util.*
class Solution {
fun calculate(s: String): Int { var operand = 0 var sign = 1 var result = 0 val stack = Stack<Int>() for (char in s) { when (char) { in '0'..'9' -> { operand = operand * 10 + (char - '0') } '+' -> { result += sign * operand sign = 1 operand = 0 } '-' -> { result += sign * operand sign = -1 operand = 0 } '(' -> { result += sign * operand stack.push(result) stack.push(sign) sign = 1 result = 0 } ')' -> { result += sign * operand result *= stack.pop() result += stack.pop() operand = 0 } } } return result + sign * operand } }
|