刷题的日常-2023年4月10日
一天一题,保持脑子清爽
链表中的下一个更大节点
来自leetcode的 1019 题,题意如下:
给定一个长度为
n的链表head对于列表中的每个节点,查找下一个 更大节点 的值。也就是说,对于每个节点,找到它旁边的第一个节点的值,这个节点的值 严格大于 它的值。
返回一个整数数组
answer,其中answer[i]是第i个节点( 从1开始 )的下一个更大的节点的值。如果第i个节点没有下一个更大的节点,设置answer[i] = 0。
理解题意
通过题意,我们可以将信息整理如下:
- 题目给出一个链表头节点
- 要求我们找出每个节点之后,第一个比自身节点要大的值,如果没有,则为0
- 返回结果数组
做题思路
这道题其实可以暴力解决,直接获取链表中所有的值。然后对每个节点,往后查找第一个大于它的值,如果找不到,则赋值为0。
但是我们可以有更好的做法,从题意可以看出,这道题可以用单调栈来做。对于栈中的数据,我们要维护两个信息,一个是节点的索引,一个是节点的值。这样我们才可以对原来的值进行覆盖。既然是单调栈,那就要保证栈中的数据不能小于当前节点,否则就必须覆盖原信息。
做题步骤如下:
- 开辟一个数组保存结果
- 开辟一个栈维护单调信息
- 循环遍历链表,如果当前节点不大于栈顶节点,则直接放入
- 否则需要进行弹栈,覆盖原索引位置信息
- 返回结果
代码实现
代码实现如下:
public class Solution {
public int[] nextLargerNodes(ListNode head) {
List<Integer> tmp = new ArrayList<>();
int idx = 0;
Stack<int[]> stack = new Stack<>();
while (head != null) {
if (stack.isEmpty() || head.val <= stack.peek()[1]) {
stack.push(new int[]{idx++, head.val});
tmp.add(0);
head = head.next;
continue;
}
while (!stack.isEmpty() && head.val > stack.peek()[1]) {
tmp.set(stack.pop()[0], head.val);
}
stack.push(new int[]{idx++, head.val});
tmp.add(0);
head = head.next;
}
int[] res = new int[tmp.size()];
for (int i = 0; i < tmp.size(); i++) {
res[i] = tmp.get(i);
}
return res;
}
}