给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
示例 1:
输入:s = “3+2*2”
输出:7
示例 2:
输入:s = " 3/2 "
输出:1
示例 3:
输入:s = " 3+5 / 2 "
输出:5
栈
class Solution {
public:
int calculate(string s) {
stack<int> st;
int i = 0;
int n = s.size();
char preSign = '+';
while(i < n){
if(s[i] == ' '){
i++;
continue;
}
long long num = 0;
while(i < n && s[i] >= '0' && s[i] <= '9'){
num = num * 10 + s[i] - '0';
i++;
}
if (i == n || !isdigit(s[i])) {
if(preSign == '+'){
st.push(num);
}
else if(preSign == '-'){
st.push(-num);
}
else if(preSign == '/'){
int t = st.top() / num;
st.pop();
st.push(t);
}
else if(preSign == '*'){
int t = st.top() * num;
st.pop();
st.push(t);
}
preSign = s[i];
num = 0;
}
i++;
}
int res = 0;
while(!st.empty()){
res += st.top();
st.pop();
}
return res;
}
};
时间复杂度和空间复杂度双O(N)
这道题我们要解决的问题就是,我们需要先计算乘和除,那么我们就可以使用栈,当遇到符号是加号或者减号的时候,推入num或者-num到栈中,然后遇到乘号或者除号,就在栈顶上进行运算。
然后我们定义一个preSign来储存计算的符号,当遍历到加减乘除的时候,我们会将当前符号前面的num与栈顶的元素进行运算。举个例子输入:s = " 3+5 / 2 "
,那么当我们遍历3的时候,会被储存在num中,当遇到加号的时候,就会将num给push到栈中,然后将preSign更新为加号,然后遍历到5,记录到num中,然后空格跳过,接下来遇到除号,我们这时候不进行除号运算,而是进行前面preSign的运算,preSign是加号,也就是继续将5推入栈中,运算完后将preSign更新为除号,然后遍历2,记录num=2,这时候经过while循环的i++,此时i=n,触发了if判断,此时preSign为除号,将栈顶的5除以当前的num值2。
最后我们只需要将栈中所有元素加起来即可,最终运算结果是5。