|
| 1 | +/* |
| 2 | + * @Author: Chacha |
| 3 | + * @Date: 2022-04-24 16:01:51 |
| 4 | + * @Last Modified by: Chacha |
| 5 | + * @Last Modified time: 2022-04-24 16:51:35 |
| 6 | + */ |
| 7 | + |
| 8 | +/** |
| 9 | + * 来源:https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/solution/ |
| 10 | + * |
| 11 | + * 150. 逆波兰表达式求值 |
| 12 | + * |
| 13 | + * 根据 逆波兰表示法,求表达式的值。 |
| 14 | + * 有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 |
| 15 | + * 注意 两个整数之间的除法只保留整数部分。 |
| 16 | + * 可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。 |
| 17 | + * |
| 18 | + * 逆波兰表达式: |
| 19 | + * 逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面: |
| 20 | + * 1. 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。 |
| 21 | + * 2. 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。 |
| 22 | + * |
| 23 | + * 逆波兰表达式主要有以下两个优点: |
| 24 | + * 1. 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。 |
| 25 | + * 2. 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。 |
| 26 | + * |
| 27 | + * |
| 28 | + * 示例 1: |
| 29 | + * 输入:tokens = ["2","1","+","3","*"] |
| 30 | + * 输出:9 |
| 31 | + * 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9 |
| 32 | + * |
| 33 | + * 示例 2: |
| 34 | + * 输入:tokens = ["4","13","5","/","+"] |
| 35 | + * 输出:6 |
| 36 | + * 解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6 |
| 37 | + * |
| 38 | + * 示例 3: |
| 39 | + * 输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"] |
| 40 | + * 输出:22 |
| 41 | + * 解释:该算式转化为常见的中缀算术表达式为: |
| 42 | + * ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 |
| 43 | + * = ((10 * (6 / (12 * -11))) + 17) + 5 |
| 44 | + * = ((10 * (6 / -132)) + 17) + 5 |
| 45 | + * = ((10 * 0) + 17) + 5 |
| 46 | + * = (0 + 17) + 5 |
| 47 | + * = 17 + 5 |
| 48 | + * = 22 |
| 49 | + * |
| 50 | + * |
| 51 | + * 提示: |
| 52 | + * 1. 1 <= tokens.length <= 10^4 |
| 53 | + * 2. tokens[i] 是一个算符("+"、"-"、"*" 或 "/"),或是在范围 [-200, 200] 内的一个整数 |
| 54 | + * |
| 55 | + */ |
| 56 | + |
| 57 | +#include <iostream> |
| 58 | +#include <vector> |
| 59 | +#include <stack> |
| 60 | + |
| 61 | +using namespace std; |
| 62 | + |
| 63 | +class Solution |
| 64 | +{ |
| 65 | +public: |
| 66 | + int evalRPN(vector<string> &tokens); |
| 67 | + |
| 68 | + bool isNumber(string &token) |
| 69 | + { |
| 70 | + return !(token == "+" || token == "-" || token == "*" || token == "/"); |
| 71 | + } |
| 72 | +}; |
| 73 | + |
| 74 | +/** |
| 75 | + * 方法一:栈 |
| 76 | + * |
| 77 | + * 逆波兰表达式严格遵循「从左到右」的运算。计算逆波兰表达式的值时,使用一个栈存储操作数,从左到右遍历逆波兰表达式,进行如下操作: |
| 78 | + * 1. 如果遇到操作数,则将操作数入栈; |
| 79 | + * 2. 如果遇到运算符,则将两个操作数出栈,其中先出栈的是右操作数,后出栈的是左操作数,使用运算符对两个操作数进行运算,将运算得到的新操作数入栈。 |
| 80 | + * |
| 81 | + * 整个逆波兰表达式遍历完毕之后,栈内只有一个元素,该元素即为逆波兰表达式的值。 |
| 82 | + * |
| 83 | + * 时间复杂度:O(n),其中 n 是数组 tokens 的长度。需要遍历数组 tokens 一次,计算逆波兰表达式的值。 |
| 84 | + * 空间复杂度:O(n),其中 n 是数组 tokens 的长度。使用栈存储计算过程中的数,栈内元素个数不会超过逆波兰表达式的长度。 |
| 85 | + * |
| 86 | + * |
| 87 | + * 题解:https://leetcode-cn.com/problems/evaluate-reverse-polish-notation/solution/ni-bo-lan-biao-da-shi-qiu-zhi-by-leetcod-wue9/ |
| 88 | + * |
| 89 | + */ |
| 90 | +int Solution::evalRPN(vector<string> &tokens) |
| 91 | +{ |
| 92 | + stack<int> stk; |
| 93 | + int n = tokens.size(); |
| 94 | + |
| 95 | + for (int i = 0; i < n; i++) |
| 96 | + { |
| 97 | + string &token = tokens[i]; |
| 98 | + |
| 99 | + if (isNumber(token)) |
| 100 | + { |
| 101 | + stk.push(atoi(token.c_str())); |
| 102 | + } |
| 103 | + else |
| 104 | + { |
| 105 | + int num2 = stk.top(); |
| 106 | + stk.pop(); |
| 107 | + |
| 108 | + int num1 = stk.top(); |
| 109 | + stk.pop(); |
| 110 | + |
| 111 | + switch (token[0]) |
| 112 | + { |
| 113 | + case '+': |
| 114 | + stk.push(num1 + num2); |
| 115 | + break; |
| 116 | + |
| 117 | + case '-': |
| 118 | + stk.push(num1 - num2); |
| 119 | + break; |
| 120 | + |
| 121 | + case '*': |
| 122 | + stk.push(num1 * num2); |
| 123 | + break; |
| 124 | + |
| 125 | + case '/': |
| 126 | + stk.push(num1 / num2); |
| 127 | + break; |
| 128 | + |
| 129 | + default: |
| 130 | + break; |
| 131 | + } |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + return stk.top(); |
| 136 | +}; |
| 137 | + |
| 138 | +int main(int argc, char const *argv[]) |
| 139 | +{ |
| 140 | + Solution s; |
| 141 | + vector<string> tokens = {'2', '1', '+', '3', '*'}; |
| 142 | + vector<string> tokens1 = {'10', '6', '9', '3', '+', '-11', '*', '/', '*', '17', '+', '5', '+'}; |
| 143 | + |
| 144 | + cout << "tokens = ['2', '1', '+', '3', '*'], 运算结果为: " << s.evalRPN(tokens) << endl; |
| 145 | + cout << "tokens = ['10', '6', '9', '3', '+', '-11', '*', '/', '*', '17', '+', '5', '+'], 运算结果为: " << s.evalRPN(tokens1) << endl; |
| 146 | + |
| 147 | + return 0; |
| 148 | +} |
0 commit comments