class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
//本题答案完全来自牛客er“子夜降晴空”,我只是做出一些自己的解释,如有侵权请联系删除!
/*对于该问题,可以使用递归的思路,我们知道一个简单的计算器是很容易实现的,
只需要将所有的数按优先级进行加减即可,本题的难点在于对括号的处理。
因为简单的计算器容易实现,我们就可以做出联想,是否有办法将复杂的括号优先级转化为
简单的计算呢?这就是递归可以做的事情,将括号问题拆解为数个简单计算。
具体的思路如下:
一、先设置一个栈,后续需要简单运算的数据都存入栈中
二、将问题拆解为简单运算,这里使用if判断,如果遇到左括号说明已经需要进入
拆解步骤,使用递归对本函数进行调用,遇到左括号进行一层递归,遇到右括号则退出一层递归
三、完善简单计算器,将计算结果返回*/
int solve(string s) {
// write code here
stack<int> sum;
int ret{};//最后返回的结果,跟递归无关
char sign='+';//计算的前一个符号
/*简单计算器的难点:例如“2+1*5”,我们在获取到加号的时候,其实是不知道下一个加数是多少的
,因此计算就进行不下去。要解决这个问题,我们可以把原式看成“0+2+1*5”,也就是在前面添加一个0.这样就能把符号往前推一位,在遇到2+某个数的时候,先把0+2计算出来;在遇到1*5的时候,先把1入栈,此时符号更新为乘号,最后
再利用top()函数乘上5,这样就能解决我们看不到参与运算的下一个数的问题*/
int num{};//对字符串的数字进行记录
for(int i=0;i<s.size();i++)//遍历字符串
{
if(s[i]>='0'&&s[i]<='9')
{
num=num*10+s[i]-'0';//将字符数字转化为整数
}
if(s[i]=='(')//遇到左括号,准备进入递归
{
int left=i++;//定位左括号的位置
int cnt=1;//左括号的数量加一,可以理解为递归层数
while(cnt>0)//对左括号进行配对,找到与之对应的右括号,对中间的括号进行忽略
{
if(s[i]=='(')
{
cnt++;
}
else if(s[i]==')')
{
cnt--;
}
i++;//每次循环都会i++,这是为了定位右括号的位置
}
num=solve(s.substr(left+1,i-2-left));//递归调用自身,将括号内的数据进行调用
i--;//i--是为了消除循环后多的那一次i++
}
if(i==s.size()-1||s[i]=='+'||s[i]=='-'||s[i]=='*')//判断是否遇到运算符或即将运算结束
{
if(sign=='+')//这里的sign是前一个符号,理解了这一点下面都能看懂
{
sum.push(num);
}
else if(sign=='-')
{
sum.push(-num);//遇到减号就加上其相反数
}
else if(sign=='*')
{
sum.top()*=num;//这里遇到乘号直接用栈顶数据乘num,不用入栈,这是优先级的体现
}
sign=s[i];//更新当前符号
num=0;//重置num
}
}
while(!sum.empty())//对栈内数据进行累加并返回结果
{
ret+=sum.top();
sum.pop();
}
return ret;
}
};