题目链接

后缀表达式求值

题目描述

给定一个后缀表达式s,计算它的结果。 例如,1+1对应的后缀表达式为1#1#+#作为操作数的结束符号。 表达式中只含有+-*三种运算,不包含除法。 本题保证表达式一定合法,且计算过程和计算结果的绝对值一定不会超过 long long

示例1 输入: "1#1#+" 输出: 2

示例2 输入: "12#3#+15#*" 输出: 225

解题思路

后缀表达式(也称逆波兰表达式)求值是栈的经典应用。我们从左到右扫描表达式,遇到数字就进栈,遇到运算符就出栈两个数字计算,然后将结果压入栈中。

具体步骤如下:

  1. 初始化一个空栈:这个栈用来存放待计算的操作数。
  2. 遍历表达式字符串:从左到右逐个字符处理。
  3. 处理操作数:如果当前字符是数字,我们需要继续向后读取,直到遇到#为止,这样可以解析出可能的多位数。然后将这个完整的数字字符串转换为整数,压入栈中。
  4. 处理运算符:如果当前字符是+-*,就从栈中弹出两个元素。注意弹出的顺序,第一个弹出的是右操作数,第二个弹出的是左操作数。
  5. 计算并入栈:用弹出的运算符对这两个数进行计算,然后把计算结果压回栈中。
  6. 返回结果:当整个表达式遍历完毕后,栈中只会留下一个元素,这个元素就是表达式的最终结果。

代码

class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 给定一个后缀表达式,返回它的结果
     * @param str string字符串
     * @return long长整型
     */
    long long legalExp(string str) {
        stack<long long> s;
        for (int i = 0; i < str.length(); ) {
            if (isdigit(str[i])) {
                long long num = 0;
                while (i < str.length() && str[i] != '#') {
                    num = num * 10 + (str[i] - '0');
                    i++;
                }
                s.push(num);
            } else if (str[i] == '+' || str[i] == '-' || str[i] == '*') {
                long long b = s.top(); s.pop();
                long long a = s.top(); s.pop();
                if (str[i] == '+') s.push(a + b);
                else if (str[i] == '-') s.push(a - b);
                else s.push(a * b);
                i++;
            } else { // 跳过 '#'
                i++;
            }
        }
        return s.top();
    }
};
import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 给定一个后缀表达式,返回它的结果
     * @param str string字符串
     * @return long长整型
     */
    public long legalExp(String str) {
        Stack<Long> stack = new Stack<>();
        for (int i = 0; i < str.length(); ) {
            char c = str.charAt(i);
            if (Character.isDigit(c)) {
                long num = 0;
                while (i < str.length() && str.charAt(i) != '#') {
                    num = num * 10 + (str.charAt(i) - '0');
                    i++;
                }
                stack.push(num);
            } else if (c == '+' || c == '-' || c == '*') {
                long b = stack.pop();
                long a = stack.pop();
                switch (c) {
                    case '+':
                        stack.push(a + b);
                        break;
                    case '-':
                        stack.push(a - b);
                        break;
                    case '*':
                        stack.push(a * b);
                        break;
                }
                i++;
            } else { // 跳过 '#'
                i++;
            }
        }
        return stack.pop();
    }
}
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
# 给定一个后缀表达式,返回它的结果
# @param str string字符串
# @return long长整型
#
class Solution:
    def legalExp(self, str: str) -> int:
        stack = []
        i = 0
        n = len(str)
        while i < n:
            if str[i] in "+-*":
                b = stack.pop()
                a = stack.pop()
                if str[i] == '+':
                    stack.append(a + b)
                elif str[i] == '-':
                    stack.append(a - b)
                elif str[i] == '*':
                    stack.append(a * b)
                i += 1
            elif str[i] == '#':
                i += 1
            else:  # 数字
                j = i
                while j < n and str[j] != '#':
                    j += 1
                stack.append(int(str[i:j]))
                i = j
        
        return stack[0]

算法及复杂度

  • 算法:栈
  • 时间复杂度,其中 是输入字符串的长度。我们只需要对字符串进行一次完整的遍历。
  • 空间复杂度,其中 是表达式中操作数的数量。栈所需空间取决于表达式中同时存在于栈中的最大操作数数量。在最坏情况下(例如 "1#2#3#...#+*..."),空间复杂度可能接近