A clear explanation of finding the next greater value for each node in a linked list using a monotonic stack.
Problem Restatement
We are given the head of a singly linked list.
For each node, we want to find the value of the next node that has a strictly greater value.
If no such node exists, the answer for that node is 0.
Return an array of these answers.
The official constraints state that the number of nodes is in [1, 10^4] and 1 <= Node.val <= 10^9.
Input and Output
| Item | Meaning |
|---|---|
| Input | Head of a singly linked list |
| Output | Array where result[i] is the next greater value for node i, or 0 |
Function shape:
def nextLargerNodes(head: Optional[ListNode]) -> list[int]:
...Examples
Example 1:
head = [2, 1, 5]| Node | Value | Next Greater |
|---|---|---|
| 0 | 2 | 5 |
| 1 | 1 | 5 |
| 2 | 5 | 0 |
Answer:
[5, 5, 0]Example 2:
head = [2, 7, 4, 3, 5]| Node | Value | Next Greater |
|---|---|---|
| 0 | 2 | 7 |
| 1 | 7 | 0 |
| 2 | 4 | 5 |
| 3 | 3 | 5 |
| 4 | 5 | 0 |
Answer:
[7, 0, 5, 5, 0]Key Insight
This is the classic “next greater element” problem.
Use a monotonic stack:
- Maintain a stack of indices whose next greater element has not yet been found.
- For each new value, pop all indices from the stack whose values are smaller than the current value.
- The current value is the next greater element for all those popped indices.
Algorithm
- Convert the linked list to an array of values.
- Initialize
result = [0] * n. - Use a stack of indices.
- For each index
iand valuev:- While the stack is non-empty and
values[stack[-1]] < v:- Pop
jfrom the stack. result[j] = v.
- Pop
- Push
ionto the stack.
- While the stack is non-empty and
- Return
result.
Correctness
The stack always contains indices in increasing order with values in decreasing order (monotone decreasing from bottom to top).
When a new value v is larger than the value at the top of the stack, the top’s next greater element is v.
After processing all elements, remaining stack entries have no next greater element, so they keep their default value of 0.
Edge Cases
- The stack should store exactly the unresolved items needed by the invariant.
- Process equal values deliberately; many monotonic-stack problems differ only in
<versus<=. - Flush or inspect the remaining stack after the scan if unresolved items still contribute to the answer.
Complexity
| Metric | Value | Why |
|---|---|---|
| Time | O(n) | Each element is pushed and popped at most once |
| Space | O(n) | Stack and result array |
Common Pitfalls
- Do not optimize away the invariant; the code should still make it clear what condition is being maintained.
- Prefer problem-specific names over one-letter variables once the logic becomes stateful.
Implementation
from typing import Optional
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def nextLargerNodes(self, head: Optional[ListNode]) -> list[int]:
values = []
node = head
while node:
values.append(node.val)
node = node.next
n = len(values)
result = [0] * n
stack = []
for i, v in enumerate(values):
while stack and values[stack[-1]] < v:
j = stack.pop()
result[j] = v
stack.append(i)
return resultCode Explanation
Convert linked list to array:
values = []
node = head
while node:
values.append(node.val)
node = node.nextUse a monotonic stack of indices:
for i, v in enumerate(values):
while stack and values[stack[-1]] < v:
j = stack.pop()
result[j] = v
stack.append(i)When v is larger than the value at index stack[-1], that index’s next greater element is v.
Remaining stack entries keep result[j] = 0.
Testing
def make_list(vals):
dummy = ListNode()
cur = dummy
for v in vals:
cur.next = ListNode(v)
cur = cur.next
return dummy.next
def run_tests():
s = Solution()
assert s.nextLargerNodes(make_list([2, 1, 5])) == [5, 5, 0]
assert s.nextLargerNodes(make_list([2, 7, 4, 3, 5])) == [7, 0, 5, 5, 0]
assert s.nextLargerNodes(make_list([1, 7, 5, 1, 9, 2, 5, 1])) == [7, 9, 9, 9, 0, 5, 0, 0]
assert s.nextLargerNodes(make_list([1])) == [0]
print("all tests passed")
run_tests()| Test | Expected | Why |
|---|---|---|
[2,1,5] | [5,5,0] | Both 2 and 1 see 5 as next greater |
[2,7,4,3,5] | [7,0,5,5,0] | Standard monotonic stack result |
[1,7,5,1,9,2,5,1] | [7,9,9,9,0,5,0,0] | 9 resolves many pending nodes |
[1] | [0] | Single node has no next |