对于上述两个要求,我们要考虑的是两点,一是处理运算优先级的问题,二是处理括号的问题。
处理优先级问题,那必定是乘号有着优先运算的权利,加号减号先一边看,我们甚至可以把减号看成加一个数的相反数,则这里只有乘法和加法,那我们优先处理乘法,遇到乘法,把前一个数和后一个数乘起来,遇到加法就把这些数字都暂时存起来,最后乘法处理完了,就剩余加法,把之前存起来的数字都相加就好了。
处理括号的问题,我们可以将括号中的部分看成一个新的表达式,即一个子问题,因此可以将新的表达式递归地求解,得到一个数字,再运算
class Solution {
public:
int solve(string s) {
int res = 0; //用于返回当前字符串的计算结果
stack<int> sum; //用于求和
char sign = '+'; //记录前一个符号,初始化为+,因为可以看成当前字符串前先加0
int num = 0; //用于将连续数字字符串转化成数字或者记录递归结果
for(int i = 0; i < s.size(); i++) { //遍历每一个字符
if(s[i] >= '0' && s[i] <= '9') //先处理数字字符
num = 10 * num + s[i] - '0'; //进位后加个位数
if(s[i] == '(') { //对于括号
int left = i++, count = 1; //用left记录最左括号位置,count记录左括号数,i当成右指针右移一格
while(count > 0) { //最终目的是找到与最左括号匹配的右括号,类似于栈操作
if(s[i] == '(') count++;
else if(s[i] == ')') count--;
i++;
}
num = solve(s.substr(left + 1, i - left - 2)); //迭代计算括号内数值,注意不要包含最左最右括号,不然会死循环
i--; //此时i是最右括号下一位,需要左移一位防止最右括号在字符串尾时发生越界从而使下面的判定失效
}
if(i == s.size() - 1 || s[i] == '+' || s[i] == '-' || s[i] == '*') { //对于字符串尾,或者加减乘,此时我们用的符号是上一次的,结算当前数字
if(sign == '+') sum.push(num); //加法入栈 注意s【i】和 sign 根本不是一个东西, sign 默认是+,刚进来不管是什么都会第一 push num =0,0+ 此时s【i】肯定是符号,不然也不会进到这个if语句。
public:
int solve(string s) {
int res = 0; //用于返回当前字符串的计算结果
stack<int> sum; //用于求和
char sign = '+'; //记录前一个符号,初始化为+,因为可以看成当前字符串前先加0
int num = 0; //用于将连续数字字符串转化成数字或者记录递归结果
for(int i = 0; i < s.size(); i++) { //遍历每一个字符
if(s[i] >= '0' && s[i] <= '9') //先处理数字字符
num = 10 * num + s[i] - '0'; //进位后加个位数
if(s[i] == '(') { //对于括号
int left = i++, count = 1; //用left记录最左括号位置,count记录左括号数,i当成右指针右移一格
while(count > 0) { //最终目的是找到与最左括号匹配的右括号,类似于栈操作
if(s[i] == '(') count++;
else if(s[i] == ')') count--;
i++;
}
num = solve(s.substr(left + 1, i - left - 2)); //迭代计算括号内数值,注意不要包含最左最右括号,不然会死循环
i--; //此时i是最右括号下一位,需要左移一位防止最右括号在字符串尾时发生越界从而使下面的判定失效
}
if(i == s.size() - 1 || s[i] == '+' || s[i] == '-' || s[i] == '*') { //对于字符串尾,或者加减乘,此时我们用的符号是上一次的,结算当前数字
if(sign == '+') sum.push(num); //加法入栈 注意s【i】和 sign 根本不是一个东西, sign 默认是+,刚进来不管是什么都会第一 push num =0,0+ 此时s【i】肯定是符号,不然也不会进到这个if语句。
else if(sign == '-') sum.push(-num); //减法相当于加负数 sing具有滞后性,进去的数字是根据sign上一次更新的值来确定进了if之后进去那个分支的,是s【i】是判断要不要进去if的,两码事情
else if(sign == '*') sum.top() *= num; //乘法与栈顶相乘
sign = s[i]; //更新符号,若为末尾的右括号也无妨,因为马上就退出循环了
num = 0; //重置当前数
}
}
while(!sum.empty()) { //将栈内所有数字相加
res += sum.top();
sum.pop();
}
return res; //返回当前字符串计算结果
}
};
else if(sign == '*') sum.top() *= num; //乘法与栈顶相乘
sign = s[i]; //更新符号,若为末尾的右括号也无妨,因为马上就退出循环了
num = 0; //重置当前数
}
}
while(!sum.empty()) { //将栈内所有数字相加
res += sum.top();
sum.pop();
}
return res; //返回当前字符串计算结果
}
};