227. 基本计算器 II
难度中等534
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
示例 1:
输入: s = "3+2*2"
输出: 7
示例 2:
输入: s = " 3/2 "
输出: 1
示例 3:
输入: s = " 3+5 / 2 "
输出: 5
解题思路:本题的题目中只有数字和加减乘除没有括号,加减运算法低,乘除运算高,所以当时加减法时,我们可以根基前一个运算法是什么,如果是乘除就可以先将乘除法先计算了,还有就是优先级高的也可以先计算了,然后再计算剩下的加减法,写的过程当初忽略的问题:
1.s是一段字符串,需要处理多位数
2.字符串中有空的字符
3.s非常长的时候会出现超时
代码如下:
var calculate = function(s) {
//保存是字符串的数字,包括计算后的数字
let s1 = [];
//保存未计算的加减乘除符号
let s2 = [];
//因为有的字符串是大于十的所以需要拼接后再转换成数字,处理多位数
let val = '';
//记录符号优先级,加减等于0,乘除等于1
let type = 0;
//遍历s拆除出数字和字符方便计算
for(let i = 0; i < s.length; i ++){
//过滤字符串中的空字符
if(s[i] !== ' '){
//计算加减法前面乘除法,碰到符号val才是一个完整的数字,这样做是为了处理多位数
switch(s[i]){
case '+':
case '-':
//type的关于1就说明加减法前一个是优先级高的,可以直接先计算,val是符号前一个数字还没有加入s1,需要判断是直接加还是计算后在加入,
if(type === 1){
//s2.pop()删除上一个符号,因为计算过了,所以删除
if(s2.pop() === '*'){
//s1.pop()得到的是当前符号的上上一个数字,val是当前符号的前面数字,例如:3 * 2 + 1,3就是s1.pop(),2就是val,
s1.push(s1.pop() * parseInt(val));
}else{
//同上
s1.push(parseInt(s1.pop() / parseInt(val)));
}
}else {
//如1+2+3这种情况,val就是2,下面s2.push(s[i])就是将3前面的加号保存下来,后面计算
s1.push(parseInt(val));
}
s2.push(s[i]);
//运算级别是0
type = 0;
//运算符后面的数字重新开始
val = '';
break;
case '*':
case '/':
// 1*2*3比如这种情况此时val=2,所以可以先将前面乘号先计算,下面注释同上面加减法计算
if(type === 1){
if(s2.pop() === '*'){
s1.push(s1.pop() * parseInt(val));
}else{
s1.push(parseInt(s1.pop() / parseInt(val)));
}
}else{
s1.push(parseInt(val));
}
s2.push(s[i]);
type = 1;
val = '';
break;
default :
//多位数拼接
val += s[i];
break;
}
//上面计算了优先级高的乘除法,下面将计算已保存的加减法计算,放在这里处理,而不是放在for循环外是为了处理字符串超长所导致的超时处理,及时计算已遍历的加减法
while(s2.length > 0 && s1.length >= 2 && s2[1] !== '*' && s2[1] !== '/'){
if(s2.shift() === '+'){
s1.unshift(s1.shift() + s1.shift());
}else{
s1.unshift(s1.shift() - s1.shift());
}
}
}
}
//因为我们是碰到符号才将符号前面的数字保存,所以最后一个数字没法保存打s1中
s1.push(parseInt(val));
//因为如果最后一个字符没法计算,所以到了这一步s2只有两种可能,一种是只剩一个运算符,或者两个运算符最后一个是乘或者除法
if(s2.length === 1){
switch (s2.pop()){
case '+':
s1.unshift(s1.shift() + s1.shift());
break;
case '-':
s1.unshift(s1.shift() - s1.shift());
break;
case '*':
s1.unshift(s1.shift() * s1.shift());
break;
case '/':
s1.unshift(parseInt(s1.shift() / s1.shift()));
break;
}
}
//因为最后两个字符可能是优先级低再高,所以最后两个字符没法计算,所以最后两个运算符最后一个是乘或者除法
if(s2.length === 2){
if(s2.pop() === '*'){
s1.push(s1.pop() * s1.pop());
}else{
s1.push(parseInt(s1[1] / s1[2]));
s1.splice(1,2);
}
if(s2.pop() === '+'){
s1.unshift(s1.shift() + s1.shift())
}else{
s1.unshift(s1.shift() - s1.shift())
}
}
//计算到最后s1只是最后计算结果
return s1[0];
};