方法一:栈(迭代)——思路与代码要点
核心想法:用两个栈——nums 存放数字、ops 存放运算符。遍历字符串:
- 遇到数字,解析完整的多位整数并入
nums。 - 遇到
(,直接入ops。 - 遇到
),一直弹出ops并对nums做计算,直到遇到对应的(。 - 遇到运算符(
+ - *),在入栈之前先把ops栈顶上优先级 >= 当前运算符的那些都执行掉(注意(是阻断符),然后再把当前运算符入栈。 - 遍历结束后把剩余运算都执行完。
这利用算术优先级(* 高于 +/-)和括号优先规则保证正确顺序。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int solve(string s) {
return calculate_stack(s);
}
private:
int applyOp(int a, int b, char op) {
if (op == '+') return a + b;
if (op == '-') return a - b;
if (op == '*') return a * b;
return 0;
}
int calculate_stack(const string &s) {
stack<int> nums;
stack<char> ops;
unordered_map<char, int> prec = {{'+',1},{'-',1},{'*',2}};
int n = s.size();
for (int i = 0; i < n; ) {
char ch = s[i];
if (ch == ' ') {
i++;
continue;
}
if (isdigit(ch)) {
int num = 0;
while (i < n && isdigit(s[i])) {
num = num * 10 + (s[i]-'0');
i++;
}
nums.push(num);
continue;
}
if (ch == '(') {
ops.push(ch);
} else if (ch == ')') {
while (!ops.empty() && ops.top() != '(') {
int b = nums.top(); nums.pop();
int a = nums.top(); nums.pop();
nums.push(applyOp(a,b,ops.top()));
ops.pop();
}
if (!ops.empty()) ops.pop(); // 弹出'('
} else { // 运算符
while (!ops.empty() && ops.top() != '(' && prec[ops.top()] >= prec[ch]) {
int b = nums.top(); nums.pop();
int a = nums.top(); nums.pop();
nums.push(applyOp(a,b,ops.top()));
ops.pop();
}
ops.push(ch);
}
i++;
}
while (!ops.empty()) {
int b = nums.top(); nums.pop();
int a = nums.top(); nums.pop();
nums.push(applyOp(a,b,ops.top()));
ops.pop();
}
return nums.top();
}
};
方法二:递归(分治 + 当前层栈)——思路与代码要点
核心想法:用递归来处理括号。写一个 helper(i),从位置 i 开始解析“当前层”到遇到 )(或字符串结尾)为止,返回该层的计算结果与解析停下的位置索引。当前层内部按同样的规则处理运算优先级:用一个局部 vector<int> stk 存放所有加/减项,但在遇到 * 时直接与栈顶合并(实现乘法优先)。
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
int solve(string s) {
int idx = 0;
return helper(s, idx);
}
private:
int helper(const string &s, int &i) {
vector<int> stk;
int num = 0;
char sign = '+';
while (i < (int)s.size()) {
char ch = s[i];
if (isdigit(ch)) {
num = num * 10 + (ch - '0');
}
if (ch == '(') {
i++;
num = helper(s, i);
}
if ((!isdigit(ch) && ch != ' ') || i == (int)s.size()-1) {
if (sign == '+') stk.push_back(num);
else if (sign == '-') stk.push_back(-num);
else if (sign == '*') stk.back() *= num;
sign = ch;
num = 0;
}
if (ch == ')') {
return accumulate(stk.begin(), stk.end(), 0);
}
i++;
}
return accumulate(stk.begin(), stk.end(), 0);
}
};