基本思路:
- 直接进行栈模拟;
- 括号展开;
主要说一下第二种方法,是自己没想到的;
简单而言括号展开思路如下:
-
对于负号,可以直接选择忽略其性质,直接看成负数的和:
例如:-2-3-4=(-2)+(-3)+(-4)
因此每个数字前必定有各自的负号,直接忽略优先级全部相加就可以; -
对于带括号,括号前如果是+,则不用管,如果是-,则括号内全部取反;
所以可以直接用栈,保存每一层括号的前一个符号;
具体代码:
1.栈模拟:
class Solution {
public:
int calculate(string s) {
stack<char>cst;
stack<int>nst;
string ss="";
for(auto& ch:s){
if(ch!=' ')
ss+=ch;
}
s=ss;
for(int i=0;i<s.size();i++){
if(s[i]=='+'){
//判断栈顶,处理负号;
while(!cst.empty()&&cst.top()=='-'){
int b=nst.top();
nst.pop();
int a=nst.top();
nst.pop();
nst.push(a-b);
cst.pop();
}
cst.push('+');
continue;
}
if(s[i]=='-'){
//判断是符号位还是计算位;
if(i==0||s[i-1]=='('){
//如果是符号为;
nst.push(0);
cst.push('-');
}else{
//如果是计算位;
while(!cst.empty()&&cst.top()=='-'){
int b=nst.top();
nst.pop();
int a=nst.top();
nst.pop();
nst.push(a-b);
cst.pop();
}
cst.push('-');
}
continue;
}
if(s[i]=='('){
cst.push('(');
continue;
}
if(s[i]==')'){
while(cst.top()!='('){
int b=nst.top();
nst.pop();
int a=nst.top();
nst.pop();
char sign=cst.top();
cst.pop();
if(sign=='+')
nst.push(a+b);
else
nst.push(a-b);
}
cst.pop();
continue;
}
int k=0;
for(int j=i;j<s.size()&&s[j]>='0'&&s[j]<='9';j++){
k=k*10+int(s[j]-'0');
i=j;
}
nst.push(k);
}
int ret=0;
while(!cst.empty()){
int b=nst.top();
nst.pop();
int a=nst.top();
nst.pop();
char sign=cst.top();
cst.pop();
if(sign=='+')
nst.push(a+b);
else
nst.push(a-b);
}
return nst.top();
}
};
2.括号展开:
class Solution {
public:
int calculate(string s) {
int sign=1;
stack<int>st;
st.push(1);
int ret=0;
for(int i=0;i<s.size();i++){
if(s[i]==' ')
continue;
if(s[i]=='('){
st.push(sign);
continue;
}
if(s[i]==')'){
st.pop();
continue;
}
if(s[i]=='+'){
sign=st.top();
continue;
}
if(s[i]=='-'){
sign=-st.top();
continue;
}
int n=0;
for(int j=i;j<s.size()&&s[j]<='9'&&s[j]>='0';j++){
n=n*10+int(s[j]-'0');
i=j;
}
ret+=n*sign;
}
return ret;
}
};