【中等】力扣算法题解析LeetCode227:基本计算器Ⅱ

关注文末推广名片,即可免费获得本题测试源码

题目来源:LeetCode227:基本计算器Ⅱ

问题抽象: 设计算法解析并计算包含加减乘除和空格的字符串表达式,需满足以下核心需求:

  1. 表达式规则

    • 运算符包括 +, -, *, /无括号);
    • 操作数为非负整数(可能含空格分隔,无负号);
    • 整数除法截断取整(向零取整,如 5/2=2);
    • 表达式保证合法(以数字开始/结束,运算符不连续)。
  2. 优先级处理

    • 乘除法优先级高于加减法;
    • 同级运算符从左到右计算(如 3-2+1 先算减后算加)。
  3. 核心计算策略

    • 栈存储中间结果
      • 加减法:将操作数带符号压栈(+num-num);
      • 乘除法:立即与栈顶元素计算并更新栈顶(实现优先级);
    • 符号延迟更新
      • 遍历时记录当前运算符,在遇到下一运算符时触发前序计算。
  4. 复杂度约束

    • 时间复杂度 O(n)(单次遍历字符串,n 为长度);
    • 空间复杂度 O(m)(栈空间,m 为操作数数量,最坏 O(n))。
  5. 边界处理

    • 空格跳过(s.replaceAll(" ","") 非最优解,需遍历时跳过);
    • 多位数解析(连续数字字符转为整数);
    • 除法截断:7/3=2(非四舍五入);
    • 整数范围:[0, 2³¹-1](无需显式处理溢出)。

输入:字符串 s(长度 ∈ [1, 3×10⁴],如 " 3+5 / 2 "
输出:整数(计算结果,如 5


解题思路

为了高效解决基本计算器问题,我们采用一次遍历字符串的方法,同时处理运算符优先级(乘除优先于加减)。核心思路是:

  1. 遍历字符串:逐个字符处理,跳过空格,累计数字。
  2. 处理运算符:使用变量 preOp 记录上一个运算符,preNum 记录当前乘除链的结果,cur 记录当前数字。
  3. 遇到新运算符或结尾时
    • 根据 preOp 更新 preNum
      • '+'preNum = cur
      • '-'preNum = -cur
      • '*''/':立即计算 preNumcur 的乘除结果。
    • 若当前运算符是 '+''-' 或到达结尾,将 preNum 累加到最终结果 res 并重置 preNum 为 0。
  4. 更新运算符:记录当前运算符用于下一次计算。
  5. 结尾处理:遍历结束时,将最后的 preNum 累加到结果。

代码实现(Java版)🔥点击下载源码

class Solution {
    public int calculate(String s) {
        int res = 0; // 最终结果
        int preNum = 0; // 当前乘除链的结果
        int cur = 0; // 当前累计的数字
        char preOp = '+'; // 上一个运算符,初始为'+'
        int n = s.length();
        
        for (int i = 0; i <= n; i++) {
            char c = i < n ? s.charAt(i) : ' '; // 末尾用空格标记
            if (c == ' ' && i != n) continue; // 跳过非末尾空格
            
            if (c >= '0' && c <= '9') {
                cur = cur * 10 + (c - '0'); // 累计数字
            } else {
                // 根据上一个运算符更新preNum
                switch (preOp) {
                    case '+': 
                        preNum = cur; 
                        break;
                    case '-': 
                        preNum = -cur; 
                        break;
                    case '*': 
                        preNum = preNum * cur; 
                        break;
                    case '/': 
                        preNum = preNum / cur; 
                        break;
                }
                // 加减或结尾:累加preNum到res,并重置preNum
                if (c == '+' || c == '-' || i == n) {
                    res += preNum;
                    preNum = 0;
                }
                // 更新运算符(非末尾)
                if (i < n) {
                    preOp = c;
                }
                cur = 0; // 重置当前数字
            }
        }
        return res;
    }
}

代码说明

  • 变量说明
    • res:累加最终结果。
    • preNum:记录当前乘除链的中间结果(如 3*2/2 的中间结果)。
    • cur:遍历中累计的当前数字。
    • preOp:记录上一个运算符,用于决定如何更新 preNum
  • 核心逻辑
    • 数字处理:遇到数字字符时,累加到 cur
    • 运算符/结尾处理
      • 根据 preOp 更新 preNum(乘除立即计算,加减暂存带符号值)。
      • 若当前运算符是加减或到达结尾,将 preNum 累加到 res 并重置 preNum
      • 更新 preOp 为当前运算符。
  • 空格处理:非末尾空格直接跳过,不影响数字累计和运算符处理。
  • 高效性:一次遍历完成计算,空间复杂度 O(1),时间复杂度 O(n)。

提交详情(执行用时、内存消耗)

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

达文汐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值