🧠 引言
“下一个更大元素”是经典算法面试高频题目,典型题包括:
- 每日温度(LeetCode 739)
- 下一个更大元素(LeetCode 496)
- 股票价格跨度(LeetCode 901)
它们的共同特征是:
找出右边第一个比当前元素大的值或索引
本篇我们将用单调栈技巧解决这类问题,并用 JavaScript 与 Python 双语代码,彻底吃透单调栈的核心原理与实战技巧。
📦 一、什么是单调栈?
单调栈是一种栈结构,栈中元素保持单调递增或递减的顺序。
常见应用:
- 找“下一个更大/小”的值
- 区间最值维护
- 滑动窗口优化
🧪 Part 1:每日温度(LeetCode 739)
❓题目描述
给定一个整数数组 temperatures,表示每日气温。返回一个数组 answer,其中 answer[i] 是指 第 i 天后几天会变暖,若无更暖则为 0。
输入: [73,74,75,71,69,72,76,73]
输出: [1,1,4,2,1,1,0,0]
✅ 解法思路(单调递减栈)
- 遍历温度数组
- 栈中保存索引
- 当前温度大于栈顶所对应温度 → 弹出,并计算间隔天数
- 否则入栈等待配对
💻 JavaScript 实现
function dailyTemperatures(T) {
const stack = [];
const res = new Array(T.length).fill(0);
for (let i = 0; i < T.length; i++) {
while (stack.length && T[i] > T[stack[stack.length - 1]]) {
const prev = stack.pop();
res[prev] = i - prev;
}
stack.push(i);
}
return res;
}
🐍 Python 实现
def daily_temperatures(T):
stack = []
res = [0] * len(T)
for i, temp in enumerate(T):
while stack and temp > T[stack[-1]]:
prev = stack.pop()
res[prev] = i - prev
stack.append(i)
return res
🧪 Part 2:下一个更大元素(LeetCode 496)
❓题目描述
给定两个数组 nums1 和 nums2,其中 nums1 是 nums2 的子集,返回 nums1 中每个元素在 nums2 中的下一个更大值。如果没有,返回 -1。
输入: nums1 = [2,4], nums2 = [1,2,3,4]
输出: [3,-1]
✅ 解法思路
- 用单调栈预处理
nums2中每个元素的“下一个更大值” - 用哈希表保存映射关系
- 遍历
nums1查表即可
💻 JavaScript 实现
function nextGreaterElement(nums1, nums2) {
const stack = [];
const map = {};
for (let num of nums2) {
while (stack.length && num > stack[stack.length - 1]) {
map[stack.pop()] = num;
}
stack.push(num);
}
return nums1.map(n => map[n] ?? -1);
}
🐍 Python 实现
def next_greater_element(nums1, nums2):
stack = []
mapping = {}
for num in nums2:
while stack and num > stack[-1]:
mapping[stack.pop()] = num
stack.append(num)
return [mapping.get(x, -1) for x in nums1]
⚠️ 常见错误总结
| 问题 | 正确做法 |
|---|---|
| 栈中放值而不是索引(温度题) | 要用索引计算天数差值 |
| 遍历顺序写错(应左→右) | 从左到右维持递减栈 |
| 哈希表查不到值没默认 -1 | 用 ?? -1 或 .get(x, -1) |
🧩 拓展任务
- 实现“下一个更小元素”
- 改写为“左边第一个更大值”
- 实现股票价格跨度(LeetCode 901)
📚 总结一句话
单调栈的本质是“等待配对”,一旦“遇强则出”,你就能在 O(n) 时间内解决“下一个更大”类问题!
📘 下一篇预告:
第15篇:【字符串双指针高频题】回文判断、最长无重复子串双解集!