[路飞]基本计算器 II

129 阅读2分钟

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];
};