跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ 栈模拟 LeetCode 227 基本计算器 II 题解

介绍使用 C++ 栈模拟解决 LeetCode 227 基本计算器 II 问题。核心思路是利用单栈存储数字,通过记录前一个运算符处理加减乘除优先级。遍历字符串时,遇到加减法直接入栈(减法转为加负数),遇到乘除法则立即与栈顶元素计算后压回。最终对栈内元素求和得到结果。时间复杂度 O(n),空间复杂度 O(n)。需注意多位数解析及整数除法截断规则。

CloudNative发布于 2026/3/28更新于 2026/7/2447 浏览
C++ 栈模拟 LeetCode 227 基本计算器 II 题解

题目描述

题目链接:力扣 227. 基本计算器 II

题目描述:给你一个字符串表达式 s,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。你可以假设给定的表达式总是有效的。所有中间结果将在 [-2^31, 2^31 - 1] 的范围内。注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()。

示例 1: 输入:s = "3+2*2" 输出:7

示例 2: 输入:s = " 3/2 " 输出:1

示例 3: 输入:s = " 3+5 / 2 " 输出:5

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

算法原理

这道题的核心是处理加减乘除的优先级问题。由于题目不含括号,我们可以简化逻辑,用一个栈加一个符号变量就能高效完成计算。

核心逻辑:化繁为简的优先级处理

  • 用一个栈存储最终需要'加减求和'的数字(将减法转化为加负数,统一运算逻辑);
  • 用一个字符变量记录当前数字的前导符号(默认第一个数字的符号为 +,确保操作统一);
  • 遍历字符串时,遇到低优先级的'加减'直接将数字(或其相反数)入栈;遇到高优先级的'乘除',则取出栈顶元素与当前数字计算后,将结果重新压入栈,实现'先算乘除'的优先级要求。

分步模拟:模拟计算全流程

结合示例表达式 +3+5*22-5+3/2,我们一步步看栈的工作流程:

  1. 初始化与统一规则:为了方便后续操作统一,我们将第一个数字的符号 ch = '+',所有数字都需要和'前一个运算符'绑定。遍历到第一个数字 3,因符号为 +,直接将 3 压入栈,此时栈:[3]。
  2. 处理高优先级运算(乘):遇到 *(前导符号更新为 *),后续数字为 22。此时需取出栈顶元素 5(假设上下文),与 22 相乘得 110,将 110 压回栈。
  3. 处理低优先级运算(减):遇到 -(前导符号更新为 -),后续数字为 5。加减是同级运算,优先级低于乘除,因此可以先将减法对应的数字转为负数存入栈,最后统一求和。将 5 取反为 -5 入栈。
  4. 处理高优先级运算(除):遇到 /(前导符号更新为 /),后续数字为 2。取出栈顶元素与 2 做整数除法得 1,压回栈。
  5. 最终求和:遍历结束后,栈中所有元素求和,即为表达式的结果。

关键细节:多位数与空格处理

  • 多位数解析:遍历到数字时,需通过'原数字×10 + 当前字符对应的数值'拼接;
  • 空格忽略:遇到空格直接跳过,不影响数字和符号的解析。

算法逻辑总结

通过上述分步模拟,我们可以将复杂的表达式求值过程,提炼为一套清晰、可落地的核心规则:

  1. 遇到操作符(+、-、*、/):直接更新'当前运算符号'变量 ch(关键前提:第一个数字默认符号为 +);
  2. 遇到数字(含多位数): (1)先完整提取连续数字:通过'前序数字×10 + 当前字符数值'的方式,拼接出完整整数 tmp; (2)根据当前符号 ch 执行精准操作:
    • 若 ch == '+':直接将 tmp 压入栈;
    • 若 ch == '-':将 -tmp 压入栈;
    • 若 ch == '*':弹出栈顶元素,与 tmp 相乘后,将结果重新压入栈;
    • 若 ch == '/':弹出栈顶元素,与 tmp 执行'仅保留整数部分'的除法后,将结果重新压入栈。

遍历完整个字符串后,栈中存储的是所有经过'乘除优先级处理'后的加减项,只需将栈内所有元素求和,即可得到表达式的最终结果。

代码实现

class Solution {
public:
    int number(string& s, int& i) {
        int ret = 0;
        while (s[i] >= '0' && s[i] <= '9') {
            ret *= 10;
            ret += (s[i] - '0');
            i++;
        }
        return ret;
    }
    
    int calculate(string s) {
        vector<int> num;
        char ch = '+';
        int n = s.size(), i = 0;
        while (i < n) {
            if (s[i] == ' ') i++;
            else if (s[i] >= '0' && s[i] <= '9') {
                int tmp = number(s, i);
                if (ch == '+') num.push_back(tmp);
                else if (ch == '-') num.push_back(-tmp);
                else if (ch == '*') num.back() *= tmp;
                else num.back() /= tmp;
            } else {
                ch = s[i];
                i++;
            }
        }
        int ret = 0;
        for (auto e : num) ret += e;
        return ret;
    }
};

时间复杂度与空间复杂度分析

时间复杂度:O(n)
  • 核心逻辑:算法仅对字符串 s 进行一次完整遍历(i 从 0 到 n-1 逐个移动,无回退);
  • 辅助操作:数字提取、栈的压入/弹出、最终求和均为线性遍历,无嵌套循环;
  • 结论:整体时间复杂度为 O(n)(n 为字符串长度)。
空间复杂度:O(n)
  • 栈的空间消耗:最坏情况下(表达式全为加减运算),栈需要存储所有数字,空间复杂度为 O(n);
  • 辅助变量:仅使用 ch、tmp、i 等常数级变量,无额外空间消耗;
  • 结论:空间复杂度为 O(n),在常规编程场景下属于可接受范围。

总结

本文围绕力扣 227. 基本计算器 II 展开,从'算法原理 - 代码实现'三个维度完整拆解了这道经典的表达式求值问题,核心要点可总结为:

  1. 核心思路:用'单栈 + 单符号'简化传统双栈逻辑,将减法转为'加负数'、乘除优先与栈顶计算,最终通过栈内元素求和得到结果,兼顾效率与可读性;
  2. 实现关键:需注意多位数拼接、空格跳过、整数除法截断规则等细节,代码通过一次遍历完成所有逻辑,时间/空间复杂度均为 O(n),满足题目性能要求。

目录

  1. 题目描述
  2. 算法原理
  3. 算法逻辑总结
  4. 代码实现
  5. 时间复杂度与空间复杂度分析
  6. 时间复杂度:O(n)
  7. 空间复杂度:O(n)
  8. 总结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • MySQL 事务详解:ACID 属性、引擎支持与提交方式
  • Google 发布多模态嵌入模型 Gemini Embedding 2,MuleRun 推出自进化个人 AI
  • 网络安全从业者必考证书汇总:国家与行业认证详解
  • Oracle 迁移 KingbaseES:SQL 语法快速兼容实战指南
  • Python 爬取财富中国 500 强数据示例
  • 电商产品 AI 绘画提示词撰写实战指南
  • 从 Alpaca 到 ShareGPT:Llama Factory 数据格式全解析
  • 如何两个月内提升漏洞挖掘能力成为独立渗透人员
  • C++ STL list 容器特性与底层原理
  • ES6 新特性实战:进制表示、Symbol 与类继承
  • Claude Code 上手笔记:实用技巧与避坑记录
  • 基于 SpringBoot 与 Leaflet 的区域冲突可视化系统设计
  • AgentScope Java 框架入门与进阶指南
  • VS Code 远程连接时 Copilot 无法使用 Claude 模型的解决方法
  • Web 创建与设计全流程指南
  • Mac 上使用 Git 拉取项目的完整指南
  • Kubernetes 中 Command 与 Args 覆盖 Dockerfile EntryPoint 详解
  • 生成合成类算法自评估报告撰写指南与模板示例
  • Python 入门教程:从零开始到精通详解
  • RISC-V 处理器实战:Verilog RTL 设计与 FPGA 验证

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online