news 2026/6/15 10:11:39

别被字符串骗了 — 从手撸计算器到一遍过的 Basic Calculator II

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别被字符串骗了 — 从手撸计算器到一遍过的 Basic Calculator II

别被字符串骗了 — 从手撸计算器到一遍过的 Basic Calculator II

作者:Echo_Wish


先来一句实话:这道题看起来像字符串题,实际上考的是你对运算优先级、流式计算(streaming)和状态管理的理解。LeetCode 上的Basic Calculator II(只有+ - * /,没有括号)是刷题里经典的一道:既能考你写出正确的实现,也能让你在代码里体现工程思路 —— 安全、稳健、易读、可拓展。

今天咱不走过场,按“先讲直观原理 → 再讲常见思路 → 最后给出干净、高质量实现 + 解析”的路线把这题讲明白,代码里全注释,手把手教你为什么这么写。风格就像和老同学对面聊,一句话一句敲清楚。


题目回顾(一句话版)

给定一个只包含非负整数、+ - * /操作符和空格的字符串,计算并返回表达式的值。除法按截断向零(trunc toward zero)处理。保证表达式有效。

举个小例子:"3+2*2"7" 3/2 "1(整除截断);" 3+5 / 2 "5

看起来简单,但坑在这儿:*/优先级比+-高。你需要在一次线性扫描里正确处理优先级,而不是先分割再暴力算。


直观思路(口语版)

把表达式想成一条流水线:你从左到右一口气读过去,遇到数字就收集,遇到操作符就根据上一个操作符决定怎么处理当前数字。

关键思想之一是:延后 + 和 - 的求和,但立即完成 * / 的计算。也就是说,当你看到*/,你必须立刻把上一个“待加入总和”的值与当前数字做掉乘除,然后把结果继续作为“待加入总和”的值;但当你看到+-时,可以把之前的待加入值放进最终和(或栈),然后把当前数字作为新的待加入值(记号由操作决定正负)。

两种常见实现:

  1. 栈(stack)方案:遇到数字和操作符,通过栈保存中间的带符号数,*//立刻弹出栈顶与当前做运算并将结果推回;结束后把栈里所有数相加。直观但需 O(n) 额外空间(栈)。

  2. 常量空间方案(lastNum 技巧):不显式使用栈,而是维护lastNumber(相当于栈顶),result(当前总和不含lastNumber),sign(上一个操作符)。遇到+/-时把lastNumber加到result,并将lastNumber设为当前数字或其负数;遇到*//时直接修改lastNumber。遍历结束把lastNumber加到result即得答案。这个方案 O(1) 空间,直观高效。

我偏好第二种,因为更简洁、内存友好,同时逻辑也一清二楚:result固定保存那些已经“结算”的加项,lastNumber存储还没被加入result的那一项(可能被后续*//改写)。


一个示例把流程走一遍

表达式:"3+2*2-4/3"

逐步(常量空间方案):

  • 初始:result = 0,last = 0,sign = '+'
  • 读到3(num=3),下一个是+(sign=‘+’) → 遇到+:把last(0)加到result->result=0,把last = +3
  • 读到2(num=2),下一个是*(sign=‘+’, 当前符号是上一个 ‘+’)→ 遇到*:不要把last加到result,而是更新last = last * num = 3*2 = 6
  • 读到2(num=2),下一个是-(sign=‘*’) → 遇到-:把last(6)加到result->result=6,把last = -2
  • 读到4(num=4),下一个是/(sign=‘-’) → 遇到/:更新last = last / num = -2 / 4截断向零,等于0(注意符号和截断),…
  • 最终把last加回result得答案(示例用于说明,实际数值需按整数截断规则算清)。

注意截断向零的细节在 Python 中做整数除法要谨慎(负数除法需要用 int(a/b) 而不是 //,因为 // 是向下取整)。


代码实现(Python,含详细注释)

defcalculate(s:str)->int:""" 计算只包含非负整数和 + - * / 空格的表达式结果。 思路:一次遍历,维护三个变量: - result: 已经结算并加入总和的部分(不含 last_num) - last_num: 当前“待加入”的数字,这个数字会参与连续的 * / 运算 - sign: 上一个操作符(决定如何处理当前读到的数) 结束时返回 result + last_num。 注意:除法需按截断向零(trunc toward zero),在 Python 中需用 int(a / b) 来实现。 时间复杂度 O(n),空间 O(1)(不计输入字符串)。 """s=s.strip()ifnots:return0result=0# 累积的和(已结算)last_num=0# 上一个待结算的数字(可能被 * / 连续修改)num=0# 当前读取的数字sign='+'# 初始化为 '+', 便于处理第一个数字i=0n=len(s)whilei<n:ch=s[i]ifch.isdigit():# 读取完整数字(可能多位)num=num*10+(ord(ch)-ord('0'))# 如果当前字符是运算符或者到达字符串末尾,需要基于上一个 sign 把 num 处理进 last_num 或 resultif(notch.isdigit()andch!=' ')ori==n-1:ifsign=='+':# 把之前的 last_num 结算进 result,新的 last_num 为当前 numresult+=last_num last_num=numelifsign=='-':result+=last_num last_num=-numelifsign=='*':last_num=last_num*numelifsign=='/':# 在 Python 中,负数除法 // 是向下取整,不是截断向零# 使用 int(a / b) 来实现截断向零行为# 注意:last_num 可能为负数last_num=int(last_num/num)# 重置 num,并更新 sign 为当前运算符num=0sign=ch i+=1returnresult+last_num# 简单测试print(calculate("3+2*2"))# 7print(calculate(" 3/2 "))# 1print(calculate(" 3+5 / 2 "))# 5

复杂度与边界说明

  • 时间复杂度:O(n),只遍历字符串一次(数字字符也只被读一次)。
  • 空间复杂度:O(1),只用常量级额外变量。
  • 注意点:数字可能多位;字符串中有空格;必须对负数除法做截断向零(语言差异要处理)。

Echo_Wish 的一点感受(收个尾)

这类题好在它能逼着你把“算法思想”落地为“工程代码”:要考虑流式解析(stream parsing)、数字边界、符号优先级、语言语义细节(例如 Python 的除法行为),以及代码的可读性。刷题不仅是为了 AC,更是为了把“一套优雅可复用的思考方式”刻进脑子里:遇到字符串处理类的问题,先想状态机,然后把状态压缩成最小变量,这套套路以后能省你大把时间。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 15:26:59

鸿蒙 Flutter 安全组件开发:加密输入框与脱敏展示组件

一、引言 在鸿蒙&#xff08;HarmonyOS&#xff09;应用开发中&#xff0c;用户敏感信息&#xff08;如密码、手机号、身份证号&#xff09;的安全防护是核心需求之一。基于 Flutter 跨平台框架开发鸿蒙应用时&#xff0c;原生组件往往无法直接满足 “输入加密” 和 “展示脱敏…

作者头像 李华
网站建设 2026/6/15 12:50:24

Cameralink采集软件-Espeedgrab软件应用【2.存储图片和视频】

应对苛刻环境&#xff0c;-40&#xff5e;75度&#xff0c;10kv静电防护&#xff0c;工业级品质&#xff0c;便携式&#xff0c;嵌入式cameralink采集卡&#xff0c;操作软件Espeedgrab使用方法。类比iport cl-u3的软件ebus player&#xff0c;ESpeedGrab软件&#xff0c;更有…

作者头像 李华
网站建设 2026/6/15 13:23:28

JUCE音频开发框架:终极跨平台音频应用构建指南

JUCE音频开发框架&#xff1a;终极跨平台音频应用构建指南 【免费下载链接】JUCE 项目地址: https://gitcode.com/gh_mirrors/juce/JUCE JUCE音频开发框架是一个功能强大的跨平台音频应用开发工具&#xff0c;专为音乐制作人、音频工程师和开发者设计。这个开源项目提供…

作者头像 李华
网站建设 2026/6/15 15:59:57

冥想第一千七百二十九天(1729)

1.周三了&#xff0c;天气很好&#xff0c;补日记&#xff0c;右胳膊可能因为拉单杠的原因&#xff0c;做推拉门动作的时候会疼&#xff0c;下班后带着溪溪游泳也疼&#xff0c;但是刚好可以左侧换气&#xff0c;左侧换气也进步了。就是泳池的水稍微有点冷。 2.感谢父母&#x…

作者头像 李华
网站建设 2026/6/15 16:13:35

日语教程资源合集

【日语教程】安宁老师的日语课 文件大小: 40.7GB内容特色: 安宁老师系统精讲&#xff0c;40GB视频讲义&#xff0c;零到N1全覆盖适用人群: 日语零基础、考级冲刺、留学/职场需求者核心价值: 标准发音真题解析高频词汇&#xff0c;高效通关JLPT下载链接: https://pan.quark.cn/…

作者头像 李华
网站建设 2026/6/15 14:43:31

LangGraph--聊天机器人构建(3)

在人工智能快速发展的今天&#xff0c;智能聊天机器人已经不仅仅是问答工具&#xff0c;它们正在向多轮对话、知识库检索和工具调用的方向升级。本篇文章将系统讲解如何搭建一个完整的智能聊天机器人&#xff0c;涵盖多轮上下文记忆、RAG检索、以及计算器工具调用&#xff0c;并…

作者头像 李华