Leetcode227.字符串理解
参考
1. 题目描述
给定一个包含加减乘除整数运算的字符串,求其运算结果,只保留整数。
2. 样例
输入是一个合法的运算字符串,输出是一个整数,表示其运算结果。
Input: " 3+5 / 2 "
Output: 5
在这个样例中,因为除法的优先度高于加法,所以结果是 5 而非 4。
3. 思路
- 对于减法,认为是加上负数
- 设置一个辅助函数用于解析连续数字的字符串
- 在字符串的首字符之前添加一个加号,结果不变。但是组成了(运算符号,数字)的组合形式,计算一次,称为一个轮次。
- 设置两个变量left 和 right: left代表上一轮的结果之和, right代表上一轮的数字。这里需要特殊理解的是, 如果是加减法,只需要记住上一轮次最后的数字,因为此数字后可能会出现需要优先计算的乘除法,故需要记住。如果是乘除法,则直接上一轮次数字(right变量)进行乘除法运算,来刷新right的值,达到优先计算乘除法的目的。
- 需要考虑字符串中无符号 和 多个空格的情况。
- 也可以采用“栈”的思想,将栈顶的乘除法优先计算出结果,然后再把整个栈内的数字做加法运算。
4. 举例
字符串为“3-4-3/2*2“
符号 | 解析数字 | left | right |
---|---|---|---|
+ | 3 | 0 | 3 |
- | 4 | 3 | -4 |
- | 3 | -1 | 3 |
/ | 2 | -1 | -1 |
* | 2 | -1 | -2 |
5. 完整代码
#include <cassert>
#include <iostream>
#include <string>
using std::string;
// 辅函数 - parse从位置i开始的一个数字
long parseNum(const string& s, int& i) {
long n = 0;
while (i < s.length() && isdigit(s[i])) {
n = 10 * n + (s[i++] - '0');
}
return n;
}
// 辅函数 - 递归parse从位置i开始的剩余字符串
int parseExpr(const string& s, int& i) {
char op = '+';
long left = 0, right = 0;
while (i < s.length()) {
if (s[i] != ' ') {
long n = parseNum(s, i);
switch (op) {
case '+':
left += right; // 计算上一轮结果
right = n;
break;
case '-':
left += right;
right = -n;
break;
case '*':
right *= n;
break;
case '/':
right /= n;
break;
}
if (i < s.length()) {
op = s[i];
}
}
++i;
}
return left + right;
}
// 主函数
int calculate(string s) {
int i = 0;
return parseExpr(s, i);
}
int main() {
std::string str = "3-4-3/2*2+7/2";
int result = 0;
auto pre = calculate(str);
std::cout << "pre: " << pre << std::endl;
assert(result == pre);
return 0;
}