[路飞]_一起刷leetcode 227. 基本计算器 II

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

题目

227. 基本计算器 II

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

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

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 1 <= s.length <= 3 * 105
  • s 由整数和算符 ('+', '-', '*', '/') 组成,中间由一些空格隔开
  • s 表示一个 有效表达式
  • 表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1] 内
  • 题目数据保证答案是一个 32-bit 整数

思路

  1. 先通过字符串的replace把表达式中的空格全都去掉;
  2. 一次遍历,对数据进行切割,明确一点:先乘除再加减;
  3. 定义变量prev记录表达式, 遇到"+"或者"-"就进行切割, 然后对表达式进行求解, 因为这时候的表达式可能含有"*"或者"/";
  4. 计算乘除:定义变量lastFlag记录当前出现的符号,第一轮从1开始开始当前值, 下一轮就根据lastFlag判断执行乘法还是除法,除法记得要向下取整;
  5. 定义变量result, 从第二个"*"或者"/"开始,不断统计前面的表达式, 记得要统计上最后一个数字,你可以再循环结束再调用一次计算,这里我选择循环加一次,在最后一次去进行计算;
  6. 计算加减: 定义变量lastFlag记录当前出现的符号,第一轮从0开始加上当前值, 下一轮就根据lastFlag判断执行加法还是减法;
  7. 定义变量result, 累加每一个切割出来的表达式的结果。

实现

/**
 * @param {string} s
 * @return {number}
 */
function calculate(s) {
    // 先去除括号
    s = s.replace(" ", "");

    // 根据 +- 切割, 然后执行 * /
    const n = s.length;
    let prev = "";
    let result = 0;
    // 记录最后一个出现的符号,决定我们待会儿加还是减
    let lastFlag = "+";
    for (let i = 0; i <= n; i++) {
        // 如果是加减符号,就计算前面的prev,有乘除先执行计算
        // i === n 是为了统计最后一个数字的运算,骚操作
        if (s[i] === "+" || s[i] === "-" || i === n) {
            // 计算加减法的表达式
            let number = getStringValue(prev);
            if (lastFlag === "-") {
                number *= -1;
            }
            result += number;
            lastFlag = s[i];
            prev = "";
        } else {
            prev += s[i];
        }
    }
    return result;
};

// 计算乘除表达式
function countStringValue(s) {
    const n = s.length;
    // prev 用来记录当前的数字
    let prev = "";
    // 乘除记得从1开始, 不能从0开始
    let result = 1;
    // 统计最后一个出现的字符是乘法还是除法
    let lastFlag = "*";
    for (let i = 0; i <= n; i++) {
        // 如果是符号,说明前面的数字到头了,先计算上一轮的结果
        // 比如 3 * 4 / 5 ,到 "/" 的时候计算 前面 3 * 4 的值
        // i === n 是为了把最后一轮的结果执行
        if (s[i] === "*" || s[i] === "/" || i === n) {
            // 除法需要向下取整, 写法多样 
            // ~~5.1 === 5.1 | 0 === Math.floor(5.1) 前两个是位运算
            if (lastFlag === "/") {
                result = ~~(result / Number(prev));
            } else {
                result *= Number(prev) 
            }
            // 记录当前的符号,下一轮拿到完整的第二个数字再执行运算
            lastFlag = s[i];
            prev = "";
        } else {
            prev += s[i];
        }
    }
    return result;
}

复制代码

看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。

猜你喜欢

转载自juejin.im/post/7033784982040494116
今日推荐