news 2026/11/2 18:27:05

LeetCode 496题解析:单调栈解决下一个更大元素问题

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LeetCode 496题解析:单调栈解决下一个更大元素问题

1. 题目背景与核心思路

LeetCode 496题"下一个更大元素 I"是单调栈算法的经典入门题目。题目给定两个没有重复元素的数组nums1和nums2,其中nums1是nums2的子集。要求找出nums1中每个元素在nums2中对应位置的下一个更大元素。

这个问题的关键在于理解"下一个更大元素"的定义:对于nums2中的一个元素x,其下一个更大元素是x右侧第一个比x大的元素。如果不存在这样的元素,则输出-1。例如:

  • 输入:nums1 = [4,1,2], nums2 = [1,3,4,2]
  • 输出:[-1,3,-1]
  • 解释:
    • 数字4在nums2中没有下一个更大元素,所以输出-1
    • 数字1的下一个更大元素是3
    • 数字2在nums2中没有下一个更大元素,所以输出-1

2. 暴力解法与复杂度分析

最直观的解法是暴力双重循环:

  1. 遍历nums1中的每个元素
  2. 在nums2中找到该元素的位置
  3. 从该位置开始向右扫描,找到第一个更大的元素

Python实现代码:

def nextGreaterElement(nums1, nums2): result = [] for num in nums1: index = nums2.index(num) found = -1 for i in range(index+1, len(nums2)): if nums2[i] > num: found = nums2[i] break result.append(found) return result

时间复杂度分析:

  • 外层循环遍历nums1:O(m)
  • index()操作:O(n)
  • 内层查找下一个更大元素:最坏O(n)
  • 总时间复杂度:O(m*n)
  • 空间复杂度:O(1)(不考虑输出结果的空间)

这种解法在小规模数据上可行,但当数组长度较大时(如n=10^5),性能会急剧下降。

3. 单调栈优化解法

单调栈是解决"下一个更大元素"类问题的标准解法,可以将时间复杂度优化到O(n)。

3.1 单调栈核心思想

单调栈维护一个栈结构,保证栈内元素从栈底到栈顶是单调递减的。处理每个元素时:

  1. 当前元素 <= 栈顶元素:直接入栈
  2. 当前元素 > 栈顶元素:不断弹出栈顶元素,直到满足单调性,同时记录这些被弹出元素的下一个更大元素就是当前元素

这种方法的精妙之处在于:

  • 每个元素最多入栈和出栈各一次
  • 在出栈时就能确定其下一个更大元素
  • 最终留在栈中的元素就是没有下一个更大元素的

3.2 具体实现步骤

  1. 使用哈希表记录nums2中每个元素的下一个更大元素
  2. 初始化一个空栈和空哈希表
  3. 遍历nums2中的每个元素:
    • while栈不为空且当前元素 > 栈顶元素:
      • 弹出栈顶元素,并在哈希表中记录其下一个更大元素为当前元素
    • 将当前元素压入栈中
  4. 遍历nums1,从哈希表中查询结果

Python实现代码:

def nextGreaterElement(nums1, nums2): stack = [] mapping = {} for num in nums2: while stack and num > stack[-1]: mapping[stack.pop()] = num stack.append(num) # 栈中剩余元素没有下一个更大元素 while stack: mapping[stack.pop()] = -1 return [mapping[num] for num in nums1]

3.3 复杂度分析

时间复杂度:

  • 遍历nums2构建哈希表:O(n)
  • 遍历nums1查询结果:O(m)
  • 总时间复杂度:O(m + n)

空间复杂度:

  • 栈空间:最坏O(n)
  • 哈希表:O(n)
  • 总空间复杂度:O(n)

4. 算法优化与边界处理

4.1 空间优化技巧

可以进一步优化空间使用,在构建哈希表的同时处理nums1:

def nextGreaterElement(nums1, nums2): stack = [] mapping = {} for num in nums2: while stack and num > stack[-1]: mapping[stack.pop()] = num stack.append(num) # 直接处理nums1,不需要先处理栈中剩余元素 return [mapping.get(num, -1) for num in nums1]

这种写法利用了Python字典的get方法,对于没有在mapping中的key(即没有下一个更大元素的),直接返回-1。

4.2 边界条件处理

需要考虑的特殊情况:

  1. 空数组输入:应返回空列表
  2. nums1包含nums2中没有的元素:根据题意,nums1是nums2的子集,所以理论上不会出现
  3. 重复元素:题目已说明所有元素都是唯一的

防御性代码示例:

def nextGreaterElement(nums1, nums2): if not nums1 or not nums2: return [] stack = [] mapping = {} for num in nums2: while stack and num > stack[-1]: mapping[stack.pop()] = num stack.append(num) return [mapping.get(num, -1) for num in nums1]

5. 单调栈的变种与应用

5.1 相关LeetCode题目

单调栈可以解决一系列类似问题:

    1. 下一个更大元素 II(循环数组)
    1. 下一个更大元素 III(数字重组)
    1. 每日温度
    1. 柱状图中最大的矩形
    1. 接雨水

5.2 循环数组的处理

对于循环数组(即最后一个元素的下一个元素是第一个元素),可以通过将数组长度翻倍来模拟循环:

def nextGreaterElements(nums): n = len(nums) res = [-1] * n stack = [] for i in range(2 * n): while stack and nums[i % n] > nums[stack[-1]]: res[stack.pop()] = nums[i % n] if i < n: stack.append(i) return res

5.3 实际应用场景

单调栈在以下场景中有重要应用:

  1. 股票价格分析:寻找下一个更高价格
  2. 编译器优化:寄存器分配
  3. 数据库查询优化:范围查询
  4. 图形处理:寻找轮廓线

6. 常见错误与调试技巧

6.1 新手常见错误

  1. 栈空判断遗漏:在while循环中忘记检查stack是否为空
  2. 元素相等处理:题目要求严格大于,所以等于的情况不应弹出
  3. 哈希表初始化:忘记处理栈中剩余元素
  4. 索引混淆:在处理循环数组时容易搞混原始索引和扩展后的索引

6.2 调试方法

  1. 打印中间状态:在循环中打印栈和哈希表的状态
for num in nums2: print(f"Processing {num}, stack: {stack}, mapping: {mapping}") while stack and num > stack[-1]: popped = stack.pop() mapping[popped] = num print(f"Popped {popped}, mapped to {num}") stack.append(num)
  1. 小规模测试用例:使用简单例子手动验证
nums1 = [2,4] nums2 = [1,2,3,4]
  1. 边界测试:空数组、单元素数组、完全递减数组等

7. 算法扩展与思考

7.1 双向处理

除了从左到右处理,也可以考虑从右到左处理:

def nextGreaterElement(nums1, nums2): stack = [] mapping = {} for num in reversed(nums2): while stack and num >= stack[-1]: stack.pop() mapping[num] = stack[-1] if stack else -1 stack.append(num) return [mapping[num] for num in nums1]

7.2 并行计算优化

对于大规模数据,可以考虑:

  1. 分块处理数组
  2. 使用多线程或GPU加速
  3. 预处理和缓存常用查询

7.3 进阶思考题

  1. 如果允许重复元素,算法应该如何修改?
  2. 如何同时找到上一个更小和下一个更大的元素?
  3. 如何扩展到多维数据?
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 18:20:49

本地语音合成实战:搭建VoiceStudio,实现稳定可控的AI配音

配音这行当&#xff0c;这两年真是被技术翻了个底朝天。我自己做了七八年视频内容&#xff0c;以前最头疼的就是配音&#xff1a;找主播录&#xff0c;一分钟少说几十块&#xff0c;遇上状态不好还得反复返工&#xff1b;自己上麦克风&#xff0c;声线不专业&#xff0c;听众一…

作者头像 李华
网站建设 2026/11/2 18:17:47

本地语音合成工作流VoiceStudio:从TTS到音色克隆的全链路实践

一开始我只是想批量给短视频做配音&#xff0c;最后却搭出了一个本地版的 VoiceStudio。这名字听着唬人&#xff0c;其实就是一个把音频采集、降噪、AI 语音合成、音色克隆、字幕对齐全部串成一条流水线的个人项目&#xff0c;全流程跑在本地机器上。适合三类人&#xff1a;嫌线…

作者头像 李华
网站建设 2026/11/2 18:13:10

Nacos常见报错分类与解决方案全解析

1. Nacos常见报错问题分类与解决方案Nacos作为阿里巴巴开源的服务发现和配置管理平台&#xff0c;在实际使用过程中可能会遇到各种报错问题。根据多年运维经验&#xff0c;我将Nacos常见报错分为以下几类&#xff1a;1.1 启动类报错No DataSource set错误&#xff1a; 这是Naco…

作者头像 李华
网站建设 2026/11/2 18:13:06

ArcGIS VCT工具箱V1.2实战:GDB与VCT转换、参数避坑与验收

简介&#xff1a;面向从事第三次全国土地调查及国土空间数据整理的技术人员&#xff0c;这套 ArcGIS 国土三调 VCT 工具箱 V1.2 聚焦 VCT 矢量数据与 FGDB 之间的转换、检查与成果整理&#xff0c;适合需要批量处理调查数据、减少手工操作的中级 GIS 用户。压缩包共 7 个文件&a…

作者头像 李华
网站建设 2026/11/2 18:11:50

RedHawk v18.1手册精读:电源完整性签核与IR Drop/EM实战

接手一份两千多页的 PDF 用户手册&#xff0c;绝大多数人的第一反应都是先存进硬盘&#xff0c;然后用 CtrlF 搜两下&#xff0c;最后在项目 deadline 前夜对着报错信息抓头发。我拿到RedHawk 用户手册 v18.1的时候也差不多&#xff0c;那时候手里的项目是一个中等规模的 SoC&a…

作者头像 李华
网站建设 2026/11/2 18:09:30

安卓开发核心技术:Kotlin与Jetpack实战指南

1. 安卓开发工程师职业全景安卓开发工程师作为移动互联网时代的关键技术岗位&#xff0c;承担着将创意转化为数亿用户手中应用的重要使命。这个岗位不仅要求扎实的编程功底&#xff0c;更需要理解移动设备的特性与用户行为模式。当前行业数据显示&#xff0c;全球安卓设备激活量…

作者头像 李华