题目
给定一个长度为 n 的链表 head
对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。
返回一个整数数组 answer ,其中 answer[i] 是第 i 个节点( 从1开始 )的下一个更大的节点的值。如果第 i 个节点没有下一个更大的节点,设置 answer[i] = 0 。
示例 1:
输入:head = [2,1,5]
输出:[5,5,0]
示例 2:
输入:head = [2,7,4,3,5]
输出:[7,0,5,5,0]
提示:
- 链表中节点数为 n
- 1 <= n <= 104
- 1 <= Node.val <= 109
解题思路
1.首先遍历链表得到链表的长度 n,然后创建长度为 n 的结果数组 answer,再次遍历链表寻找每个结点的下一个更大结点的值。
2.当遍历到第 i 个结点时,将当前结点的值记为 val,执行如下操作。如果栈不为空且栈顶元素的结点值小于 val,则将栈顶元素的下标对应的下一个更大结点的值设为 val,并将栈顶元素出栈,重复该操作直到栈为空或者栈顶元素的结点值大于等于 val。
将 i 和 val 的二元组入栈。
3.上述操作中,i 和 val 的二元组入栈的条件是栈为空或者栈顶元素的结点值大于等于 val,因此可以保证从栈底到栈顶的元素的结点值非严格单调递减。
单调栈做法的正确性说明如下。
4.当遍历到第 j 个结点时,假设栈顶元素的下标是 i,其中 i<j。如果第 i 个结点的值小于第 j 个结点的值,则第 i 个结点的下一个更大结点的值一定是第 j 个结点的值。假设存在下标 k 满足 i<k<j 且第 k 个结点的值大于第 i 个结点的值,则在遍历到第 k 个结点时会将第 i 个结点的下标和结点值出栈,遍历到第 j 个结点时栈内不可能存在第 i 个结点的下标和结点值。因此当遍历到第 j 个结点时如果栈顶元素的下标是 i,则一定不存在下标范围 [i+1,j−1] 中的结点的值大于第 i 个结点的值。
代码实现
class Solution {
public int[] nextLargerNodes(ListNode head) {
int n = 0;
ListNode cur = head;
while(cur != null){
n++;
cur = cur.next;
}
int[] answer = new int[n];
Deque<int[]> stack = new ArrayDeque<int[]>();
cur = head;
for(int i = 0; i < n; i++){
int val = cur.val;
while(!stack.isEmpty() && stack.peek()[1] < val){
answer[stack.pop()[0]] = val;
}
stack.push(new int[]{i,val});
cur = cur.next;
}
return answer;
}
}
测试结果