刷题的日常-链表中的下一个更大节点

88 阅读2分钟

刷题的日常-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;
    }

}

image.png