说实话,我觉得这道题的难度不应该是简单。
众所周知,前、后缀表达式是可以用栈求解,那就从栈的角度去考虑这一题。
我也不知道怎么想出来这种做法(直觉?),所以直接说做法吧。
遇到一个数字时,我们将其加入栈0中。
遇到一个运算符时,我们要先判断它与栈1(储存运算符)栈顶运算符的优先级:
- 如果当前运算符的优先级大于栈1栈顶元素的优先级,则应计算当前运算符,再计算栈中运算符,此时直接将运算符入栈。
- 否则,按照优先级的定义,应先计算栈中的运算符,循环处理,直至栈顶运算符的优先级小于当前运算符的优先级,按照步骤1处理。
遇到左括号,直接入栈1。
遇到右括号,则一直取栈1栈顶元素,并取栈0元素进行运算,直至栈1栈顶元素是左括号为止。
这里主要解释一下两个点:
- 左括号的优先级要定义的最小,这样才能先计算左括号后面的内容(即括号内)。因为如果不这样做的话,会将左括号错认为运算符并进行运算。
- 遇到右括号时,不断取栈1顶元素是可以保证优先级正确的。这是因为,根据我们遇到运算符的操作,所有优先级比x(x为任意运算符)高的运算符(也就是要比x先算)肯定已经计算过了,且已经出栈。这就可以保证:对于栈1内的任意元素,在它之前的运算符的优先级一定比它低(也就是要比它后算)。
由上述第2点,我们可以推出,当遍历完整个输入字符串之后,栈1中所剩运算符的优先级一定是从栈顶往前递减的,所以直接按顺序出栈计算即可。
可以这样证明:
如果栈1内运算符(非栈顶)的优先级大于栈顶运算符的优先级,则它应该在程序遍历到栈顶这一运算符时已经出栈了,它不可能在栈1中,入栈了,但没有完全入栈,故栈1中所剩运算符的优先级一定是从栈顶往前递减的。
至于代码实现,大家可以看看别的楼的。
补充:如果运算符优先级相同,一定要先计算先入栈的,因为$a-b+c$不等于$a-(b+c)$。
形象一点,可以这样看:
当优先级相同时,从左往右计算相当于从左往右打括号,也就是${[(a-b)+c]-d}$。这么做是对的,是因为保证了第一个数是正整数。括号前肯定没有负号。
而从右往左算,就有问题了,因为运算符可能是负号,也就是${a-[b+(c-d)]}$,括号前面可能出现负号,所以是错误的。
【算法基础课】题解整合
qwq