leetcode:227. 基本计算器 II
题目
给你一个字符串表达式 s
,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1]
的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()
。
示例:
输入:s = "3+2*2"
输出:7
输入:s = "3+2*2"
输出:7
输入:s = " 3+5 / 2 "
输出:5
输入:s = "1-1+1"
输出:1
解答 & 代码
栈:保存整数
- 核心思想:先进行所有乘除操作(乘除法优先于加减法体现在,乘除法可以和栈顶的数结合,而加减法只能把自己放入栈)
- 如果是加号 or 减号之后的数字,直接将数字压入栈中(减号取相反数)
- 如果是乘除号之后的数字,则直接先于栈顶元素进行乘除法计算,并替换栈顶元素为计算后的结果
- 遍历字符串,并用变量
preSign
记录整数之前的符号(初始化为'+'
)- 每次遍历完一个整数,根据
preSign
决定操作:- 如果
preSign
是乘除号,则将栈顶数值和当前整数相乘 or 相除后,替换栈顶 - 如果
preSign
是减号,则将当前整数的相反数压入栈中 - 如果
preSign
是加号,则将当前整数直接压入栈中
- 如果
- 每次遍历完一个整数,根据
最后将栈中所有整数相加,就是最终的计算结果
class Solution {
public:
int calculate(string s) {
stack<int> numS; // 栈,保存整数
char preSign = '+'; // 之前的符号,初始化为 '+'
int idx = 0;
// 遍历字符串
while(idx < s.size())
{
char ch = s[idx];
// 1. 若当前字符是空格,则跳过
if(ch == ' ')
++idx;
// 2. 若当前字符是符号,则更新 preSign
else if(ch == '+' || ch == '-' || ch == '*' || ch == '/')
{
preSign = ch;
++idx;
}
// 3. 若当前字符是数字,则遍历完该整数
else if(ch >= '0' && ch <= '9')
{
// 遍历得到当前整数
int num = 0;
while(idx < s.size() && s[idx] >= '0' && s[idx] <= '9')
{
num = num * 10 + (s[idx] - '0');
++idx;
}
// 如过 preSign 是 * or /,则将栈顶数值和当前整数相乘 or 相除,来替换栈顶
if(preSign == '*')
numS.top() *= num;
else if(preSign == '/')
numS.top() /= num;
// 如果 preSign 是 -,则将当前整数的相反数压入栈中
else if(preSign == '-')
numS.push(-num);
// 如果 preSign 是 +,则直接将当前整数压入栈中
else
numS.push(num);
}
}
// 将栈中所有整数相加,就是最终的计算结果
int result = 0;
while(!numS.empty())
{
result += numS.top();
numS.pop();
}
return result;
}
};
复杂度分析:设字符串
s
长为 N
- 时间复杂度 O(N):
- 空间复杂度 O(N):
执行结果:
执行结果:通过
执行用时:4 ms, 在所有 C++ 提交中击败了 96.49% 的用户
内存消耗:8.4 MB, 在所有 C++ 提交中击败了 63.84% 的用户