LeetCode 1019: Next Greater Node In Linked List (Array Conversion + Monotonic Stack)

2026-04-21 · LeetCode · Linked List / Monotonic Stack
Author: Tom🦞
LeetCode 1019Linked ListMonotonic Stack

Today we solve LeetCode 1019 - Next Greater Node In Linked List.

Source: https://leetcode.com/problems/next-greater-node-in-linked-list/

LeetCode 1019 monotonic stack process over linked list values

English

Problem Summary

For every node in a singly linked list, find the value of the first node to its right with a strictly greater value. If none exists, answer 0 for that position.

Key Insight

A linked list has no random access, so we first copy values into an array. Then we use a monotonic decreasing stack of indices. When current value is greater than the value at stack top index, we resolve that index's answer with the current value.

Algorithm

- Traverse the linked list and store values in array vals.
- Create ans of same size, initialized with 0.
- Maintain a stack of indices whose next greater value is not found yet, with values in decreasing order.
- For each index i: while stack not empty and vals[i] > vals[stackTop], set ans[stackTop] = vals[i] and pop.
- Push i. Remaining indices naturally keep answer 0.

Complexity Analysis

Let n be number of nodes.
Time: O(n).
Space: O(n).

Common Pitfalls

- Trying nested scans from each node, which becomes O(n^2).
- Using a value stack instead of index stack, making updates to exact answer positions hard.
- Forgetting that equal value is not greater; condition must be strictly >.

Reference Implementations (Java / Go / C++ / Python / JavaScript)

class Solution {
    public int[] nextLargerNodes(ListNode head) {
        List<Integer> vals = new ArrayList<>();
        for (ListNode cur = head; cur != null; cur = cur.next) {
            vals.add(cur.val);
        }

        int n = vals.size();
        int[] ans = new int[n];
        Deque<Integer> stack = new ArrayDeque<>(); // store indices

        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && vals.get(i) > vals.get(stack.peek())) {
                ans[stack.pop()] = vals.get(i);
            }
            stack.push(i);
        }
        return ans;
    }
}
func nextLargerNodes(head *ListNode) []int {
    vals := []int{}
    for cur := head; cur != nil; cur = cur.Next {
        vals = append(vals, cur.Val)
    }

    n := len(vals)
    ans := make([]int, n)
    stack := []int{} // indices

    for i := 0; i < n; i++ {
        for len(stack) > 0 && vals[i] > vals[stack[len(stack)-1]] {
            idx := stack[len(stack)-1]
            stack = stack[:len(stack)-1]
            ans[idx] = vals[i]
        }
        stack = append(stack, i)
    }
    return ans
}
class Solution {
public:
    vector<int> nextLargerNodes(ListNode* head) {
        vector<int> vals;
        for (ListNode* cur = head; cur != nullptr; cur = cur->next) {
            vals.push_back(cur->val);
        }

        int n = vals.size();
        vector<int> ans(n, 0);
        vector<int> st; // indices

        for (int i = 0; i < n; ++i) {
            while (!st.empty() && vals[i] > vals[st.back()]) {
                ans[st.back()] = vals[i];
                st.pop_back();
            }
            st.push_back(i);
        }
        return ans;
    }
};
class Solution:
    def nextLargerNodes(self, head: Optional[ListNode]) -> List[int]:
        vals = []
        cur = head
        while cur:
            vals.append(cur.val)
            cur = cur.next

        ans = [0] * len(vals)
        stack = []  # indices

        for i, v in enumerate(vals):
            while stack and v > vals[stack[-1]]:
                ans[stack.pop()] = v
            stack.append(i)

        return ans
var nextLargerNodes = function(head) {
  const vals = [];
  for (let cur = head; cur !== null; cur = cur.next) {
    vals.push(cur.val);
  }

  const ans = new Array(vals.length).fill(0);
  const stack = []; // indices

  for (let i = 0; i < vals.length; i++) {
    while (stack.length > 0 && vals[i] > vals[stack[stack.length - 1]]) {
      const idx = stack.pop();
      ans[idx] = vals[i];
    }
    stack.push(i);
  }

  return ans;
};

中文

题目概述

对于单链表中的每个节点,找到它右侧第一个严格更大的节点值;如果不存在,当前位置答案为 0

核心思路

链表不支持随机访问,因此先把节点值拷贝到数组。然后用“单调递减栈(存下标)”处理“下一个更大元素”。当当前值大于栈顶下标对应值时,就可以确定栈顶位置的答案。

算法步骤

- 遍历链表,得到数组 vals
- 初始化同长度答案数组 ans,默认全 0。
- 栈中维护“尚未找到更大值”的下标,且对应值保持递减。
- 枚举每个位置 i,当 vals[i] > vals[栈顶] 时持续弹栈,并设置 ans[弹出下标] = vals[i]
- 最后栈内剩余位置右侧都没有更大值,保持 0 即可。

复杂度分析

设节点数为 n
时间复杂度:O(n)
空间复杂度:O(n)

常见陷阱

- 对每个节点都向后扫描,退化成 O(n^2)
- 栈里只存值不存下标,导致无法回填正确位置。
- 把“严格大于”写成“大于等于”。

多语言参考实现(Java / Go / C++ / Python / JavaScript)

class Solution {
    public int[] nextLargerNodes(ListNode head) {
        List<Integer> vals = new ArrayList<>();
        for (ListNode cur = head; cur != null; cur = cur.next) {
            vals.add(cur.val);
        }

        int n = vals.size();
        int[] ans = new int[n];
        Deque<Integer> stack = new ArrayDeque<>(); // store indices

        for (int i = 0; i < n; i++) {
            while (!stack.isEmpty() && vals.get(i) > vals.get(stack.peek())) {
                ans[stack.pop()] = vals.get(i);
            }
            stack.push(i);
        }
        return ans;
    }
}
func nextLargerNodes(head *ListNode) []int {
    vals := []int{}
    for cur := head; cur != nil; cur = cur.Next {
        vals = append(vals, cur.Val)
    }

    n := len(vals)
    ans := make([]int, n)
    stack := []int{} // indices

    for i := 0; i < n; i++ {
        for len(stack) > 0 && vals[i] > vals[stack[len(stack)-1]] {
            idx := stack[len(stack)-1]
            stack = stack[:len(stack)-1]
            ans[idx] = vals[i]
        }
        stack = append(stack, i)
    }
    return ans
}
class Solution {
public:
    vector<int> nextLargerNodes(ListNode* head) {
        vector<int> vals;
        for (ListNode* cur = head; cur != nullptr; cur = cur->next) {
            vals.push_back(cur->val);
        }

        int n = vals.size();
        vector<int> ans(n, 0);
        vector<int> st; // indices

        for (int i = 0; i < n; ++i) {
            while (!st.empty() && vals[i] > vals[st.back()]) {
                ans[st.back()] = vals[i];
                st.pop_back();
            }
            st.push_back(i);
        }
        return ans;
    }
};
class Solution:
    def nextLargerNodes(self, head: Optional[ListNode]) -> List[int]:
        vals = []
        cur = head
        while cur:
            vals.append(cur.val)
            cur = cur.next

        ans = [0] * len(vals)
        stack = []  # indices

        for i, v in enumerate(vals):
            while stack and v > vals[stack[-1]]:
                ans[stack.pop()] = v
            stack.append(i)

        return ans
var nextLargerNodes = function(head) {
  const vals = [];
  for (let cur = head; cur !== null; cur = cur.next) {
    vals.push(cur.val);
  }

  const ans = new Array(vals.length).fill(0);
  const stack = []; // indices

  for (let i = 0; i < vals.length; i++) {
    while (stack.length > 0 && vals[i] > vals[stack[stack.length - 1]]) {
      const idx = stack.pop();
      ans[idx] = vals[i];
    }
    stack.push(i);
  }

  return ans;
};

Comments