How to Merge K Sorted Linked Lists: Efficient Min-Heap Methods Explained

The most efficient way to merge k sorted linked lists uses a min-heap (priority queue) to achieve O(N log k) time complexity by always extracting the smallest available node and pushing its successor back onto the heap.

Merging k sorted linked lists is a fundamental algorithmic challenge frequently encountered in technical interviews at major tech companies. The kdn251/interviews repository provides a battle-tested Java implementation that leverages a priority queue to solve this problem with optimal complexity. This guide breaks down the efficient methods for merging k sorted linked lists, analyzing the source code directly from the repository's solutions.

Min-Heap (Priority Queue) Approach

The optimal solution utilizes a min-heap to track the smallest available node across all k lists simultaneously. This approach ensures that each insertion and extraction operation costs O(log k), avoiding the repeated linear scans required by naive comparison methods.

Algorithm Implementation

The implementation in leetcode/linked-list/MergeKSortedLists.java follows this exact strategy:

  1. Initialize a PriorityQueue ordered by node value with capacity k
  2. Seed the heap with the head node of each non-null list
  3. Repeatedly extract the minimum node and append it to the result list
  4. If the extracted node has a successor, push that next node into the heap
  5. Continue until no nodes remain in the heap

Complexity Analysis

  • Time Complexity: O(N log k), where N is the total number of nodes across all lists. Each node is pushed and popped exactly once, with each heap operation costing O(log k).
  • Space Complexity: O(k) for the heap storage, since at most one node from each of the k lists resides in the queue at any time. The output list reuses existing nodes, requiring only O(1) auxiliary space.

Source Code from kdn251/interviews

// File: leetcode/linked-list/MergeKSortedLists.java
public class MergeKSortedLists {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }

        // Min-heap ordered by node value
        PriorityQueue<ListNode> queue = new PriorityQueue<>(lists.length,
            (o1, o2) -> Integer.compare(o1.val, o2.val));

        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;

        // Seed heap with the first node of each list
        for (ListNode node : lists) {
            if (node != null) {
                queue.add(node);
            }
        }

        // Extract min, attach to result, and push next node from the same list
        while (!queue.isEmpty()) {
            tail.next = queue.poll();
            tail = tail.next;
            if (tail.next != null) {
                queue.add(tail.next);
            }
        }

        return dummy.next;
    }
}

Divide-and-Conquer Alternative

While the kdn251/interviews repository implements the heap solution, a divide-and-conquer method offers another O(N log k) approach. This technique recursively merges pairs of lists using the standard linear-time merge routine for two sorted lists.

Although asymptotically equivalent, the divide-and-conquer method typically incurs higher constant factors due to repeated traversal of intermediate lists and recursive overhead. The min-heap solution is generally preferred in production Java code because PriorityQueue provides a concise, highly optimized implementation with better cache locality.

Edge Case Handling

The repository's implementation demonstrates robust handling of boundary conditions common in interview scenarios:

  • Empty Input Arrays: The method returns null immediately when lists is null or lists.length == 0
  • Null List Heads: The seeding loop checks if (node != null) before adding to the queue, preventing NullPointerException when individual lists are empty
  • Dummy Node Pattern: The ListNode dummy = new ListNode(0) technique simplifies pointer manipulation and eliminates special-case logic for initializing the result list's head

Practical Usage Examples

Example 1: Merging Three Sorted Lists

// Build three sorted lists: [1→4→5], [1→3→4], [2→6]
ListNode l1 = new ListNode(1);
l1.next = new ListNode(4);
l1.next.next = new ListNode(5);

ListNode l2 = new ListNode(1);
l2.next = new ListNode(3);
l2.next.next = new ListNode(4);

ListNode l3 = new ListNode(2);
l3.next = new ListNode(6);

// Merge them
MergeKSortedLists merger = new MergeKSortedLists();
ListNode[] lists = new ListNode[]{l1, l2, l3};
ListNode merged = merger.mergeKLists(lists);

// Print merged list: 1 → 1 → 2 → 3 → 4 → 4 → 5 → 6
while (merged != null) {
    System.out.print(merged.val + (merged.next != null ? " → " : ""));
    merged = merged.next;
}

Example 2: Handling Empty or Null Lists

ListNode[] lists = new ListNode[]{null, null};
ListNode result = new MergeKSortedLists().mergeKLists(lists);
// result is null (no nodes to merge)

Repository File Locations

The min-heap implementation appears consistently across multiple company-specific interview packages in the kdn251/interviews repository:

Each file contains identical algorithmic logic, demonstrating the universal applicability of the priority queue approach for efficiently merging k sorted linked lists across different interview contexts.

Summary

  • The min-heap approach provides the optimal O(N log k) time complexity for merging k sorted linked lists, making it the standard solution for this interview problem.
  • The mergeKLists method in leetcode/linked-list/MergeKSortedLists.java implements this pattern using Java's PriorityQueue with a lambda comparator (o1, o2) -> Integer.compare(o1.val, o2.val).
  • Space efficiency is maintained at O(k) by storing at most one node from each list in the heap at any given time, reusing existing list nodes for the output.
  • Robust edge-case handling ensures the solution gracefully manages empty inputs, null lists, and varying list lengths without throwing exceptions.
  • The dummy node pattern simplifies result list construction by eliminating special-case checks for the head pointer.

Frequently Asked Questions

What is the time complexity of merging k sorted linked lists?

The optimal time complexity is O(N log k), where N represents the total number of nodes across all lists and k is the number of lists. This is achieved by using a min-heap to track the smallest available node, ensuring each of the N nodes is inserted and extracted exactly once with O(log k) cost per operation.

Why use a min-heap instead of merging lists sequentially one by one?

A min-heap avoids the O(N * k) time complexity of naive sequential merging, where repeatedly merging the accumulated result with the next list requires re-scanning previously processed elements. The heap maintains O(log k) access to the global minimum across all active lists, providing significant performance improvements when k grows large.

How does the code handle empty or null input lists?

According to the source code in MergeKSortedLists.java, the method first validates if (lists == null || lists.length == 0) and returns null immediately. When seeding the priority queue, the implementation verifies if (node != null) before adding each head node, ensuring null entries do not cause NullPointerException.

Can this approach be adapted for merging k sorted arrays instead of linked lists?

Yes, the same min-heap logic applies to arrays, though implementation details differ. Instead of pushing tail.next, you would track array indices and push the next element from the same array when extracting the minimum. The time complexity remains O(N log k), but array-based solutions may offer better cache performance than pointer-chasing through linked list nodes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →