计算器实现(携程)

71 阅读2分钟

输入一个字符串,可以包含 + - * /、数字、括号以及空格,你的算法返回运算结果 类似LeetCode224这道题 image.png

参考题解

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
}