输入一个字符串,可以包含 + - * /、数字、括号以及空格,你的算法返回运算结果
类似LeetCode224这道题
参考题解
func calculate(s string) int {
leftRightIndexMap := MappingParentheses(s)
return calculateHelper(s, 0, len(s)-1, leftRightIndexMap)
}
func calculateHelper(s string, start int, end int, leftRightIndexMap map[int]int) int {
sign := '+' // 记录 num 前的符号,首个数字为正,初始化为 +
num := 0 // 记录遍历到的当前数字,初始为0
stack := []int{}
for i := start; i<=end; i++{
if s[i] >= '0' && s[i] <= '9'{ // 遇到数字
cur := int(s[i] - '0')
num = 10*num + cur
}else if s[i] == '('{ // 遇到左括号
// 找到其匹配的右括号位置
rightIdx := leftRightIndexMap[i]
// 递归计算这个括号内的表达式结果
// 括号包含的算式,直接视为一个数字就行了,更新当前num值
num = calculateHelper(s, i+1, rightIdx-1, leftRightIndexMap)
// 下一次循环,i直接跳到rightIdx的下一个位置
i = rightIdx
}
// 因为下面包含判断是否为最后一个字符的情况,每次都要判断,不放在else中
if s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/' || i == end{ // 遇到符合或者已经来到表达式末尾
switch sign {
case '+':
// 将当前数字和其前面符号存入栈中
stack = append(stack, num)
case '-':
// 将当前数字和其前面符号存入栈中
stack = append(stack, -num)
case '*':
// 将栈顶元素出栈,与当前数字相乘,结果再入栈
last := stack[len(stack)-1]
stack = stack[:len(stack)-1]
stack = append(stack, last*num)
case '/':
// 将栈顶元素出栈,除以当前数字,结果再入栈
last := stack[len(stack)-1]
stack = stack[:len(stack)-1]
stack = append(stack, last/num)
}
// 更新符号,num清零等待处理下一个数字
sign = rune(s[i])
num = 0
}
}
// 将栈中所有结果求和就是答案
var res int
for _, v := range stack{
res += v
}
return res
}
func MappingParentheses(s string) map[int]int{
// key 是左括号的索引,value 是对应的右括号的索引
leftRightIndexMap := make(map[int]int)
stack := []int{}
for i:=0; i<len(s); i++{
if s[i] == '('{
stack = append(stack, i)
}else if s[i] == ')'{
// 弹出栈顶,即匹配的最近左括号
lastLeftIdx := stack[len(stack)-1]
stack = stack[:len(stack)-1]
leftRightIndexMap[lastLeftIdx] = i
}
}
return leftRightIndexMap
}