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. 若当前字符是符号,则更新 preSignelse 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 是 +,则直接将当前整数压入栈中elsenumS.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% 的用户
