当前位置: 首页 > news >正文

力扣(逆波兰表达式求值)

解析 LeetCode 150. 逆波兰表达式求值:栈的精准运算实践

一、题目分析

在这里插入图片描述

(一)问题定义

给定逆波兰表达式的字符串数组 tokens,计算表达式的值。需遵循规则:

  • 运算符为 +-*/
  • 除法向零截断(如 7 / -2 结果为 -3-7 / 2 结果为 -3 )。
  • 输入合法,无除零运算。

(二)核心挑战

利用栈实现逆波兰表达式的计算:遇到操作数入栈,遇到运算符则弹出栈顶两个元素(注意顺序 ),运算后结果入栈,最终栈中剩余元素即为结果。

二、算法思想:栈驱动的运算流程

(一)核心思路

逆波兰表达式的计算天然适配栈结构:

  1. 遍历 tokens:逐个处理字符串。
  2. 操作数入栈:若字符串是数字(或负号开头的数字 ),转换为整数入栈。
  3. 运算符处理:若字符串是运算符,弹出栈顶两个元素(注意先弹出的是右操作数,后弹出的是左操作数 ),按运算符规则计算,结果入栈。
  4. 结果输出:遍历结束后,栈中唯一元素即为表达式结果。

(二)关键细节

  • 运算符处理顺序:减法和除法中,先弹出的是右操作数,后弹出的是左操作数(如 a - b ,栈中先弹出 b ,再弹出 a ,计算 a - b )。
  • 数字判断优化:通过字符串长度快速筛选运算符(长度为 1 且是运算符字符 ),其余为操作数。

三、代码实现与详细解析

class Solution {public int evalRPN(String[] tokens) {// 用 ArrayDeque 实现栈,效率高于 Stack 类Deque<Integer> stack = new ArrayDeque<>(); for (String token : tokens) {  // 先处理长度为1的情况,快速识别运算符if (token.length() == 1) { char c = token.charAt(0);switch (c) {case '+': // 弹出两个操作数,相加后入栈(顺序不影响)stack.push(stack.pop() + stack.pop()); continue;case '-': // 先弹出右操作数 b,再弹出左操作数 a,计算 a - bint b = stack.pop(); stack.push(stack.pop() - b); continue;case '*': // 弹出两个操作数,相乘后入栈(顺序不影响)stack.push(stack.pop() * stack.pop()); continue;case '/': // 先弹出右操作数 b,再弹出左操作数 a,计算 a / bb = stack.pop(); stack.push(stack.pop() / b); continue;}}// 非运算符(操作数),转换为整数入栈stack.push(Integer.parseInt(token)); }// 栈中最后剩余的元素即为结果return stack.pop(); }
}

(一)代码流程拆解

  1. 栈初始化:使用 ArrayDeque 作为栈结构,相比 Stack 类,避免了线程安全带来的额外开销,效率更高。
  2. 遍历 tokens
    • 运算符判断:若 token 长度为 1,且字符是运算符(+-*/ ),进入 switch 处理。
    • 加法:弹出两个元素相加,结果入栈(加法交换律,顺序不影响 )。
    • 减法:先弹出 b(右操作数 ),再弹出 a(左操作数 ),计算 a - b 后入栈。
    • 乘法:弹出两个元素相乘,结果入栈(乘法交换律,顺序不影响 )。
    • 除法:先弹出 b(右操作数 ),再弹出 a(左操作数 ),计算 a / b 后入栈(注意向零截断 )。
    • 操作数处理:若不是运算符,转换为整数入栈。
  3. 结果返回:遍历结束后,栈中只剩一个元素,弹出即为表达式结果。

(二)关键逻辑解析

  • 运算符处理顺序:减法和除法中,严格区分左右操作数顺序,先弹出的是右操作数,确保计算符合数学规则(如 tokens = ["4", "13", "5", "/"] ,计算 4 / 13 ?不,实际是 13 是右操作数,4 是左操作数?不,原表达式是 4 13 5 / ?不,逆波兰表达式是后缀式,正确流程是:遇到 4 入栈,13 入栈,5 入栈,遇到 / ,弹出 5(右 )和 13(左 ),计算 13 / 5 = 2 ,结果入栈;再遇到可能的运算符继续。这里代码中减法和除法的处理,严格遵循 “左操作数 - 右操作数”、“左操作数 / 右操作数” 的逻辑。
  • 向零截断处理:Java 中整数除法 a / b 本身就会向零截断(如 7 / -2 = -3-7 / 2 = -3 ),无需额外处理,契合题目要求。
  • 效率优化:通过 token.length() == 1 快速筛选运算符,减少不必要的 Integer.parseInt 调用,提升效率。

四、复杂度分析

(一)时间复杂度

遍历 tokens 数组一次,每个元素的操作(入栈、出栈、运算 )都是 O(1)O(1)O(1) ,总体时间复杂度为 O(n)O(n)O(n)ntokens 数组长度。

(二)空间复杂度

栈最多存储 n/2 个操作数(最坏情况,表达式全是操作数,如 ["1", "2", "3", ...] ,但实际逆波兰表达式中操作数和运算符数量有规律,栈空间主要受操作数数量影响 ),空间复杂度为 O(n)O(n)O(n)

http://www.dtcms.com/a/351368.html

相关文章:

  • 英伟达 Spectrum-XGS:重构 AI 基础设施,开启跨域超级工厂时代
  • Day3--HOT100--42. 接雨水,3. 无重复字符的最长子串,438. 找到字符串中所有字母异位词
  • JHipster 生成器快速入门
  • 爬虫 API:从技术架构到实战落地的全维度解析
  • 功能强大的PDF工具箱-- PDF补丁丁,v1.1.0.4657新版本,免费无广告,开箱即用版~
  • HarmonyOS 中 @Observed 与 @ObjectLink:对象级别的响应式数据管理
  • 鸿蒙中使用极光推送
  • 阿里云docker搭建的mysql无法访问
  • 如何下载MySQL小白指南 (以 Windows 为例)
  • CNN 中 3×3 卷积核等设计背后的底层逻辑
  • 负载均衡之带权重的随机负载均衡算法详解与实现
  • 【LeetCode】动态规划——198.打家劫舍、213.打家劫舍||、337.打家劫舍|||
  • 开发避坑指南(37):Vue3 标签页实现攻略
  • 【Python系列】Flask 和 FastAPI对比
  • 高性价比的云手机该怎样进行选择?
  • GraphRAG——v0.3.5版本
  • 从MySQL到OpenTenBase:电商平台分布式数据库架构升级实战
  • TCP协议11种状态
  • 【人工智能AI、机器学习ML、深度学习DL、基础模型FM、LLM、GPT、Generative AI 分别是什么?他们之间的关系是什么?】
  • 一个头像图片滚动轮播组件(React实现)
  • vscode有的结构体不能补全,有的可以补全问题的解决.
  • 校园资讯平台|校园资讯平台系统|基于java和小程序的校园资讯平台设计与实现(源码+数据库+文档)
  • 《数据之心》——鱼小妖的觉醒(童年篇)
  • 【国密证书】CentOS 7 安装 GmSSL 并生成国密证书
  • SpringBoot启动优化
  • 肌肉力量训练
  • 【C语言练习】汉诺塔
  • 金融市场微观行为分析结合深度学习的大单过滤与短期价格预测框架
  • 【资源分享】破解极域电子教室
  • 【云计算】云原生(Cloud Native)