本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、题目描述:
1019. 链表中的下一个更大节点 - 力扣(LeetCode) (leetcode-cn.com)
给定一个长度为 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 <= 10^4
- 1 <= Node.val <= 10^9
二、思路分析:
- indexList 若是下一个元素比它大则存储下一个元素下标值,否则存0;在后续再次遍历填充结果数组时,会对于所存下标为0的位置进行更新;
- headList 按顺序存储原链表的val值
- 比如indexList.get(6)值为8,表示headList(6)的下一个更大节点值为headList(8)。
三、AC 代码:
public static int[] nextLargerNodes(ListNode head) {
List<Integer> indexList = new ArrayList<>();
List<Integer> headList = new ArrayList<>();
ListNode p = head;
int count = 0;
while (p != null) {
count++;
if (p.next != null && p.next.val > p.val) {
indexList.add(count);
} else {
indexList.add(0);
}
headList.add(p.val);
p = p.next;
}
int[] rstArray = new int[count];
int index = 0, j = 0;
// 从倒数第二个元素开始,反向遍历并填充结果数组
for (int i = count - 2; i >= 0; i--) {
index = indexList.get(i);
if (index != 0) {
rstArray[i] = headList.get(index);
j = index;
} else {
while (j != 0 && headList.get(j) <= headList.get(i)) {
// 以下标链式的方式,找到第一个比当前元素大的值。
j = indexList.get(j);
}
// 将比当前元素大的值的下标记录
indexList.set(i, j);
rstArray[i] = (j == 0) ? 0 : headList.get(j);
}
}
indexList.clear();
headList.clear();
return rstArray;
}
四、总结:
时间复杂度 O(n)
对链表遍历一次; 对indexList遍历一次,遍历indexList时可能会触发对下标链的查找。考虑极端情况,链表为[n,1,2,3,...,n-1],遍历到i=0时,查找下标链长度n-1,其余查找长度1,总查找长度2n-2,时间复杂度O(n)
空间复杂度 O(n)
两个大小为n的列表,一个大小为n的数组。