Want Help Cracking FAANG?

(Then click this)

×
Back to Question Bank

1019. Next Greater Node In Linked List - Leetcode Solution

Code Implementation

# Definition for singly-linked list.
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next

class Solution:
    def nextLargerNodes(self, head: ListNode) -> list[int]:
        values = []
        while head:
            values.append(head.val)
            head = head.next
        result = [0] * len(values)
        stack = []
        for i, value in enumerate(values):
            while stack and values[stack[-1]] < value:
                idx = stack.pop()
                result[idx] = value
            stack.append(i)
        return result
      
// Definition for singly-linked list.
struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(nullptr) {}
    ListNode(int x) : val(x), next(nullptr) {}
    ListNode(int x, ListNode *next) : val(x), next(next) {}
};

#include <vector>
#include <stack>
class Solution {
public:
    std::vector<int> nextLargerNodes(ListNode* head) {
        std::vector<int> values;
        while (head) {
            values.push_back(head->val);
            head = head->next;
        }
        std::vector<int> result(values.size(), 0);
        std::stack<int> stk;
        for (int i = 0; i < values.size(); ++i) {
            while (!stk.empty() && values[stk.top()] < values[i]) {
                result[stk.top()] = values[i];
                stk.pop();
            }
            stk.push(i);
        }
        return result;
    }
};
      
// Definition for singly-linked list.
class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

import java.util.*;
class Solution {
    public int[] nextLargerNodes(ListNode head) {
        List<Integer> values = new ArrayList<>();
        while (head != null) {
            values.add(head.val);
            head = head.next;
        }
        int[] result = new int[values.size()];
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < values.size(); i++) {
            while (!stack.isEmpty() && values.get(stack.peek()) < values.get(i)) {
                result[stack.pop()] = values.get(i);
            }
            stack.push(i);
        }
        return result;
    }
}
      
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {number[]}
 */
var nextLargerNodes = function(head) {
    let values = [];
    while (head) {
        values.push(head.val);
        head = head.next;
    }
    let result = new Array(values.length).fill(0);
    let stack = [];
    for (let i = 0; i < values.length; i++) {
        while (stack.length && values[stack[stack.length - 1]] < values[i]) {
            let idx = stack.pop();
            result[idx] = values[i];
        }
        stack.push(i);
    }
    return result;
};
      

Problem Description

Given the head of a singly linked list head, return an array of integers result where result[i] is the value of the next node that is greater than the value of the i-th node in the list. If there is no such node, result[i] should be 0.

Key constraints:
  • You must process the linked list in order from head to tail.
  • Each node's "next greater node" is the first node that appears after it with a strictly greater value.
  • If no such node exists, output 0 for that position.
  • There is exactly one valid solution for each input.
  • You cannot reuse nodes or values from earlier in the list.

Thought Process

At first glance, the problem resembles the classic "Next Greater Element" problem, but instead of an array, we are given a singly linked list. If we try to solve it naively, for each node, we would walk forward through the list to find the next greater node, resulting in a time-consuming nested loop.

However, as with the array version, we can optimize by using a stack. The stack allows us to keep track of nodes for which we have not yet found a next greater value. As we process each node, we check if its value is greater than the value at the top of the stack. If so, we update the result for the index at the top of the stack and pop from the stack. This process continues until the stack is empty or the current value is not greater. This approach is much more efficient and avoids unnecessary repeated traversals.

Solution Approach

To solve the problem efficiently, we use the following steps:
  1. Convert the Linked List to an Array: Since random access is easier in arrays, we first traverse the linked list and store all the node values in an array.
  2. Initialize the Result Array: We create an array of the same size as the input, filled with zeros. This will store our final answers.
  3. Use a Stack to Track Indices: We use a stack to keep track of the indices of elements for which we have not yet found the next greater value. The stack will store indices, not values, so we can update the result array directly.
  4. Iterate Through the Values: For each value in the array, we check if it is greater than the value at the index on top of the stack. If it is, we pop the index from the stack and set the corresponding position in the result array to the current value. We repeat this until the stack is empty or the current value is not greater.
  5. Push Current Index to Stack: After processing, we push the current index onto the stack. This means we are still looking for a greater value for this element.
  6. Return the Result: After processing all elements, the result array contains the next greater node values for each position (or 0 if none exists).
Why use a stack? The stack efficiently keeps track of which indices are still waiting for a next greater value, and ensures that each element is processed only once, resulting in O(n) time.

Example Walkthrough

Sample Input: head = [2, 1, 5]
Step-by-step process:
  1. Convert linked list to array: [2, 1, 5]
  2. Initialize result: [0, 0, 0]
  3. Start with empty stack: []
  4. Process index 0 (value 2):
    - Stack is empty, so push 0.
    - Stack: [0]
  5. Process index 1 (value 1):
    - 1 is not greater than 2 (value at index 0), so push 1.
    - Stack: [0, 1]
  6. Process index 2 (value 5):
    - 5 > 1 (index 1): pop 1, set result[1] = 5.
    - 5 > 2 (index 0): pop 0, set result[0] = 5.
    - Stack is now empty, push 2.
    - Stack: [2]
  7. End of array. Stack has index 2 left (no greater value), so result[2] remains 0.
  8. Final result: [5, 5, 0]
This process ensures each node gets the correct next greater value, or 0 if none exists.

Time and Space Complexity

Brute-force approach:
  • Time Complexity: O(n2), because for each node, you may need to traverse the remainder of the list to find the next greater node.
  • Space Complexity: O(n), for the result array.
Optimized stack-based approach:
  • Time Complexity: O(n), because each element is pushed and popped from the stack at most once.
  • Space Complexity: O(n), for the array of values, the result array, and the stack.
The optimized solution is much faster, especially for large input sizes, because it avoids repeated traversals.

Summary

The "Next Greater Node In Linked List" problem is efficiently solved by first converting the list to an array, then using a stack to track indices of nodes waiting for their next greater value. This approach leverages the stack to ensure each node is processed only once, resulting in an elegant O(n) solution. The key insight is transforming the linked list into a structure (array) that allows random access, and then applying the classic stack-based algorithm for next greater elements.