LeetCode 496 — 下一个更大元素 I(单调栈)WP

一、题目概述

给定两个数组nums1nums2:

  • nums1nums2的子集
  • 对于nums1中的每一个元素,需要在nums2中找到它右侧第一个比它大的元素
  • 如果不存咋,返回-1

二、暴力破解

其实一开始想到的是暴力破解:

对于nums1中的每个元素都在nums2中找到该元素的位置。再从该位置向右遍历,寻找第一个更大的数。

但是时间复杂度是O(n²),在数据量较大时效率较低。

三、优化思路

3.1 核心思想

使用单调递减栈来维护还没有找到下一个更大元素的数字。再使用哈希表记录每个数字对应的下一个更大元素。只遍历一次nums2,即可得到所有映射关系。

3.2 使用单调栈的原因

栈中元素保持从栈底到栈顶单调递减。当遇到一个更大的元素时,说明它是栈顶元素的下一个更大元素。

四、算法流程

  1. 初始化空栈 stack 和哈希表 map

  2. 遍历 nums2 中的每个元素 num

  3. 当栈不为空且 num > stack[-1] 时:

    • 弹出栈顶元素
    • 记录其下一个更大元素为 num
  4. 将当前元素 num 入栈

  5. 遍历结束后,栈中剩余元素均无更大值,映射为 -1

  6. 根据哈希表构造 nums1 的结果数组

五、代码思路解析

map = {}       # 存放每个元素的“下一个更大元素”
stack = []     # 单调递减栈,用于追踪尚未找到下一个更大元素的数字

然后遍历 nums2

for num in nums2:
    while stack and num > stack[-1]:
        top_num = stack.pop()
        map[top_num] = num    # 栈顶元素找到了下一个更大元素
    stack.append(num)         # 将当前数字压入栈

核心逻辑:

  1. 栈保存“待匹配的数字”,栈内数字是单调递减的。

  2. 遍历到一个新数字 num

    • 如果 num 比栈顶元素大,说明栈顶元素的“下一个更大元素”就是 num,于是出栈并记录。
    • 如果 num 小于或等于栈顶元素,则把 num 压入栈,等待后续数字来匹配。
  3. 遍历结束后,栈里剩下的数字没有更大元素,把它们映射为 -1

while stack:
    max_num = stack.pop()
    map[max_num] = -1

最后一步

result = [map[num] for num in nums1]
  • nums1 里只关心部分数字,所以从哈希表里直接取对应的“下一个更大元素”即可。
  • 时间复杂度 O(n),比暴力法 O(n²) 高效很多。

六、复杂度分析

  • 时间复杂度: O(n)
    每个元素最多入栈、出栈一次
  • 空间复杂度: O(n)
    使用了栈和哈希表

posted @ 2025-12-22 21:54  困困小猫log  阅读(2)  评论(0)    收藏  举报