150. 逆波兰表达式求值

142 阅读3分钟

leetcode原题链接

根据逆波兰表示法,求表达式的值。

有效的运算符包括+,-,*,/。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

说明:

整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:

输入: ["2", "1", "+", "3", "*"]
输出: 9
解释: ((2 + 1) * 3) = 9

示例 2:

输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: (4 + (13 / 5)) = 6

示例 3:

输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
输出: 22
解释: 
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

概念

有几个概念大家需要理解。

1、操作数(数字)2、运算符(顾名思义)3、分界符(括号)注意,没必要去跟中括号较劲

中括号也拿小括号来算(当然他题目不一定出的有中括号)

好,理解完这个概念我们需要理解一个叫做后缀表达式的东西。

我们在试卷上看到的计算题那个格式就是中缀表达式,人可以判断先算哪里再算哪里有智能判断。但是机器不行,机器最方便的只能顺着来,跟着特定的规律来进行计算,所以,我们需要引入一个有顺序的东西叫做后缀表达式。

举个栗子: 一个算式: 6*(3+5)/8 = 6;这是中缀表达式。3 5 + 6 * 8 / 最终等于6;这是后缀表达式。

在中缀表达式中,我们可以看到我们需要先算 3+5,而在后缀表达式中,3 5放在最前,运算符放后。以此类推,这就是后缀表达式。前缀表达式你们自己可以去看看,跟后缀表达式差不多。

思路

因为他输入进来的是一个一个字符串,所以我们要把字符串转成数字 字符串有可能不完全是操作数,也有可能是运算符(这里没有分界符)

弄一个结果栈stack,用来存放运算过程及结果,最终stack有且只有一个元素,那就是最终答案。

遍历输入的数组 如果是数字,则直接push到stack中,如果是+,-,*,/,那说明是运算符,那我就把stack的上面两个元素出栈,并赋值给num1 num2,再把他们抛给计算函数,

注意,如果是减法和除法那得反过来,stack 入栈出栈顺序是相反的!

我们要把算出来的结果再压回给stack栈,方便下一次遇到运算符运算。

以此类推,最终stack.top()就是最终结果!

func evalRPN(_ tokens: [String]) -> Int {
    var stack: Array<Int> = []
    for string in tokens {
        if "+-*/".contains(where: { String($0) == string }) {
            let left = stack.last!
            stack.removeLast()
            let right = stack.last!
            stack.removeLast()
            var temp = 0
            switch string {
            case "+": temp = right + left
            case "-": temp = right - left
            case "*": temp = right * left
            case "/": temp = right / left
            default: break
            }
            stack.append(temp)
        }
        else {
            stack.append(Int(string)!)
        }
    }
    return stack.first!
}