题目:
昨天的题目比较简单,就差把用栈写在脸上了,我就没写博客。今天这题还是有点难度的。
不过相对来说,也不算最难的那种。因为最难的话就应该把加减乘除全部搞上,当然现在的我要复习很多东西,也没有精力去研究。。。除非它每日一题出了。
那么言归正传,今天这题只有+ 和 -,其实完全可以把括号全部拆开来看待。小学数学告诉我们,拆括号的时候,前面遇到➖,是要变号的。那么这题是不是就可以考虑成,记录在什么时候需要变号就好了呢?
除此之外,我们应当选用什么数据结构来记录这个变化呢?
其实发挥一下你的编程基础,就很容易想到,不论是算式还是函数,多半都是用栈的方式存放,处理的。
我们发现题解也是这么一个思路,并且也用到了栈结构。
思路:
1.整体上来说,我们要将他们全部展开,只用特殊处理需要变号的地方即可。
2.需要变号的地方是哪些呢?是括号前面的➖会改变括号内的符号。
3.那怎么处理括号呢?
**遇到"(“的时候将前面的符号入栈,遇到”)"的时候出栈。**因为需要记录哪个符号已经失去作用了。
其余的则统一处理成数字相加,然后由标志位来决定当前是什么符号。
比如1+2-3;
我们的动态处理为1sign + 2sign + 3*sign,sign的取值在一开始是1,➕是1,➖变为-1,就可以得到原本的等式。
4.那么标志位怎么改变呢?
sign遇到+的时候,直接取栈顶元素,不用取反。而遇到-的时候,取栈顶元素取反。因为栈顶元素记录了当前是属于什么符号的括号内部,这样就可以保证整个算式运作的正确性了。
C++代码附带测试程序:
#include<iostream>
#include<stack>
using namespace std;
class Solution {
public:
int calculate(string s) {
stack<int> ops;
ops.push(1);
int sign = 1;
int ans = 0;
int n = s.length();
int i = 0;
while(i<n)
{
if(s[i]==' '){
i++;
}
else if(s[i]=='('){
ops.push(sign);
i++;
}
else if(s[i]==')'){
ops.pop();
i++;
}
else if(s[i]=='+'){
sign = ops.top();
i++;
}
else if(s[i]=='-'){
sign = -ops.top();
i++;
}
else{
int num = 0;
while(i<n&&s[i]>='0'&&s[i]<='9')
{
num = num*10 + (s[i]-'0');
i++;
}
ans += num*sign;
}
}
return ans;
}
};
int main()
{
string s = "2-1+2";
Solution solution;
cout<<solution.calculate(s)<<endl;
}
今天这题其实很巧妙。因为标志位和当前栈顶元素表达的不一样,我一开始想的是用栈顶元素去单独表达,结果可想而知那是很复杂的。但是如果标志位是单独的,标志是否需要相加还是相减,而栈顶元素去决定当前属于什么符号内部的运算,结合起来就很容易。
妙啊!