leetcdoe刷题_227. 基本计算器 II

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

题目

227. 基本计算器 II

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

示例 1:

输入:s = "3+2*2"
输出:7
复制代码

示例 2:

输入:s = " 3/2 "
输出:1
复制代码

示例 3:

输入:s = " 3+5 / 2 "
输出:5
复制代码

解法

栈数据结构

思路

我们拿到是一整串字符串,首先得知道从哪到哪是一个数字,哪里是符号,哪些是空格要跳过,然后我们才能去进行加减乘除的运算。

  1. 是否符号很好判断,直接用isNaN(a)来判断即可,由于空格也不是NaN,所以满足NaN在这里一定是符号。
  2. 判断为数字,难点在于是这里数字一个一个字符,我们得先知道这个数字字符串有多长,我们从头开始遍历,每次遇到一个值为数字的(即!isNaN(a) && a != ' '),那么我们就将当前之前的数字*10,再加上当前的数字,如321为3*10 +2,然后下一次为32*10 + 1。然后遇到下一个符号,则停止累加,进入运算环节。

由于运算是有优先级的,乘除优先于加减,那么我们得先将所有的乘除运算完,将运算的结果保存起来,最后将剩下的所有数累加即可。

具体步骤如下:

  1. 我们先申明一个栈stack,用于存储处理完的待累加的数据,默认第一个数字入栈的运算符为 “+”
  2. 遍历字符串,遇到数字则根据上面的方法得到完整数字后,根据该数字之前的那个运算符来推入栈,如果是“+”则直接推入,如果是“-”则推入数字的负数,如果是“*或/”则将栈顶元素取出来和当前数字计算,再推入,由于得到完整数字是在遇到下一个符号时确定的,所以我们这里将下一个符号给保存起来,给下一个数字运算使用。
  3. 处理完之后,我们遍历整个栈,将所有数字累加即可。

代码

/**
 * @param {string} s
 * @return {number}
 */
var calculate = function(s) {
    s = s.trim();
    let stack = [];
    let preSymbol = '+';
    let num = 0;
    for(let i=0;i<s.length;i++){
        // isNaN(' ') == false,所以判断数字的时候需要注意空格
        if(!isNaN(s[i]) && s[i] !== ' '){
            num = num*10 + Number(s[i]);
        }
        if(isNaN(s[i]) || i == s.length -1){
            switch(preSymbol){
                case '+': 
                    stack.push(num);
                    break;
                case '-': 
                    stack.push(-num);
                    break;
                case '*':
                    stack.push(stack.pop()*num);
                    break;
                case '/':
                    stack.push(parseInt(stack.pop()/num));
                    break;

            }
            preSymbol = s[i]
            num = 0;
        }
    }
    let res = 0;
    while(stack.length>0){
        res += stack.pop();
    }
    return res;
};
复制代码

复杂度分析

时间复杂度:O(n),第一遍遍历整个字符串来处理为O(n),第二遍累加最坏情况为O(n/2),故总共仍然是O(n)。

扫描二维码关注公众号,回复: 13690775 查看本文章

空间复杂度:O(n),需要一个栈来维护待相加的数,最坏情况为O(n/2),故为O(n)。

猜你喜欢

转载自juejin.im/post/7068654709233418276