LeetCode 1019. 链表中的下一个更大节点
题目描述


题意分析
对链表中的每个节点,向后寻找第一个值严格大于它的节点,返回这个更大节点的值。找不到时该位置返回零,结果数组顺序与链表节点顺序一致。
“下一个更大”指位置最近的合格节点,不一定是紧邻的下一节点,也不是后面数值最小的更大值。相同值不能作为答案;需要返回值,而不是两个节点相隔的距离。
解法:数组转换 + 单调栈
核心思路
[!blue]
单链表不能按下标直接回查旧位置,所以先沿原顺序收集节点值到数组,方便把后来找到的答案写回对应位置。这个过程只移动遍历指针,不修改原链表连接。
从左到右扫描值数组,用栈保存尚未找到更大节点的下标。栈底到栈顶下标递增,对应值非递增。当前值大于栈顶对应值时,栈顶位置第一次等到了更大值,弹出该下标并把当前值写入它的答案。
因为扫描顺序就是从近到远,某个下标一直留在栈里,说明此前没有更大节点将它弹出;当前触发弹出的一定是它右侧第一个更大值。当前值还可能同时超过新的栈顶,所以要连续弹栈,直到栈顶不再比它小。
停止时,栈里更下面的值也不小于栈顶,当前值无法解决它们;再压入当前下标,非递增关系继续保持。相等值保留等待,遍历结束还在栈中的节点后面没有更大值,维持答案默认零。
解题步骤
- 遍历链表,将节点值按原顺序存入数组,准备全零答案数组与空下标栈。
- 从左到右读取当前值,只要它严格大于栈顶对应值,就弹出旧下标。
- 将当前值写入每个被弹出下标的答案,继续检查新的栈顶。
- 无法继续匹配时,压入当前下标,等待未来更大值。
- 扫描结束直接返回结果,未被弹出的位置保持零。
代码实现
class Solution {
public int[] nextLargerNodes(ListNode head) {
List<Integer> values = new ArrayList<>();
while (head != null) {
values.add(head.val);
head = head.next;
}
int n = values.size();
int[] res = new int[n];
Deque<Integer> stack = new ArrayDeque<>();
for (int i = 0; i < n; i++) {
int val = values.get(i);
// 当前值是这些待定位置首次遇到的严格更大值。
while (!stack.isEmpty() && values.get(stack.peek()) < val) {
res[stack.pop()] = val;
}
// 相等值保留等待,栈底到顶的值不增。
stack.push(i);
}
return res;
}
}
func nextLargerNodes(head *ListNode) []int {
values := make([]int, 0)
for head != nil {
values = append(values, head.Val)
head = head.Next
}
n := len(values)
res := make([]int, n)
stack := make([]int, 0)
for i, val := range values {
// 当前值是这些待定位置首次遇到的严格更大值。
for len(stack) > 0 && values[stack[len(stack)-1]] < val {
idx := stack[len(stack)-1]
stack = stack[:len(stack)-1]
res[idx] = val
}
// 相等值保留等待,栈底到顶的值不增。
stack = append(stack, i)
}
return res
}
复杂度分析
- 时间复杂度:$O(n)$,链表转数组为线性;之后每个下标压栈一次、至多弹出一次,总比较与更新次数仍为线性。
- 空间复杂度:$O(n)$,保存节点值数组与待匹配下标栈;返回答案数组另占 $O(n)$。
关键点总结
[!green]
- 栈保存还未定案的位置,当前更大值到来时集中为它们填写答案。
- 从左到右扫描保证第一次触发匹配就是位置最近的更大节点。
- 下标用于写回原位置,值用于比较和作为答案,两种作用需要区分。
- 严格大于才匹配,相同值可以同时留在非递增栈中。
易错点总结
[!yellow]
- 使用大于等于作为匹配条件,把相同值也当成更大节点。
- 一次只弹一个下标,当前节点可能同时是多个旧位置的第一个更大值。
- 将答案写到当前下标,当前节点其实还在等待自己的后续答案;应写入被弹出的旧下标。
- 保存温差或下标距离,混淆其他单调栈题目,这里要写当前节点值。
- 对值数组排序再查更大值,破坏链表中的先后位置,无法找到最近的后续节点。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 739. 每日温度 | 中等 | 同样用单调栈记录尚未找到更大值的位置,原题返回距离,本题返回后续节点值。 |
| 496. 下一个更大元素 I | 简单 | 原题数组可直接索引,本题链表可先转成序列或在遍历时维护节点下标。 |
| 503. 下一个更大元素 II | 中等 | 用单调栈确定最近的更大元素;本题先把链表值转为顺序序列处理,该题循环扫描以覆盖跨边界候选。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!