Merge k Sorted Lists

Updated on 10 June, 2025
Merge k Sorted Lists header image

Problem Statement

In this challenge, you are provided with an array of k linked-lists named lists, where each element in lists is a singly-linked list that is already sorted in ascending order. Your task is to merge all these linked-lists into a single linked-list which is also sorted in ascending order. Ultimately, you should return this merged and sorted linked-list. Consider not only merging the values but the entire nodes of the linked lists.

Examples

Example 1

Input:

lists = [[1,4,5],[1,3,4],[2,6]]

Output:

[1,1,2,3,4,4,5,6]

Explanation:

The linked-lists are:
[
1->4->5,
1->3->4,
2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6

Example 2

Input:

lists = []

Output:

[]

Example 3

Input:

lists = [[]]

Output:

[]

Constraints

  • k == lists.length
  • 0 <= k <= 104
  • 0 <= lists[i].length <= 500
  • -104 <= lists[i][j] <= 104
  • lists[i] is sorted in ascending order.
  • The sum of lists[i].length will not exceed 104.

Approach and Intuition

Overview

The problem essentially asks for a way to integrate multiple sorted sequences into a single sorted sequence. This merging operation is a common task in algorithms involving sorted data, such as the merge step in merge sort.

Step-by-Step Process

  1. Initialization: First, a priority queue (min-heap) can be initialized to help in sorting the elements from all linked-lists in real-time.

  2. Heap Population: Insert the first node of each linked-list into the priority queue. Since these lists are sorted, initially, we only need the first element of each list to determine the smallest element.

  3. Merging Mechanism:

    • Extract the smallest element node from the heap.
    • Append the extracted node to the result linked-list.
    • Insert the next node of the extracted node's linked-list into the heap.
    • Continue this process until the heap is empty.

Example Walkthrough

  • For Example 1, the process would involve:

    • Adding the heads of all three lists 1, 1, and 2 into the heap.
    • Repeatedly: remove the smallest element from the heap, add it to the result linked-list, and add the next node of the extracted node's list to the heap.
    • This would result in the merged list [1, 1, 2, 3, 4, 4, 5, 6].
  • For Example 2, with an empty list of lists, the resulting linked-list is also empty because there are no nodes to merge.

  • In Example 3, where the list contains an empty list, the result remains an empty linked-list as there are no elements to process.

Consideration of Constraints

  • The memory efficiency hinges on keeping only k nodes in the heap at any given time, where k is the number of linked-lists.
  • The method ensures that we utilize the given fact that each individual linked-list is sorted, which simplifies our merging process since we initially consider only the first node of each linked-list.

Solutions

  • C++
  • Java
  • C
  • JavaScript
  • Python
cpp
// Definition for singly-linked list.
// struct ListNode {
//    int value;
//    ListNode *nextNode;
//    ListNode(int x) : value(x), nextNode(nullptr) {}
//};
class Solution {
public:
    ListNode* combineLists(vector<ListNode*>& multiLists) {
        vector<int> values;
        ListNode root(0);
        ListNode* current = &root;
        for (ListNode* eachList : multiLists) {
            while (eachList) {
                values.push_back(eachList->value);
                eachList = eachList->nextNode;
            }
        }
        sort(values.begin(), values.end());
        for (int val : values) {
            current->nextNode = new ListNode(val);
            current = current->nextNode;
        }
        return root.nextNode;
    }
};

The provided C++ code snippet demonstrates a strategy for merging multiple sorted linked lists into a single sorted linked list. The process involves extracting all values from the given lists into a single vector, sorting this vector, and constructing a new sorted linked list from these elements.

Here's a brief walkthrough of the code:

  • First, a ListNode structure is defined, representing the nodes of the linked lists, with constructors to facilitate easy node creation.
  • The class Solution contains the function combineLists which takes a vector of ListNode*, representing the k sorted linked lists.
  • An empty vector values is used to store the integers from the linked lists.
  • The function iterates over each linked list, traverses each one entirely, and pushes each node's value into the values vector.
  • After extracting all values, the sort function from the standard library is used to sort the values vector.
  • A temporary dummy node root is created to simplify the linked list re-construction. Linked list nodes are then appended in sorted order based on the contents of the sorted values vector.
  • The function finally returns the next node of the dummy root, which is the head of the newly created sorted linked list.

This solution is effective for a manageable number of lists and total elements but may not be optimal for large datasets due to the overhead of storing all values and sorting them. For a more efficient approach, especially with very large data, using a priority queue to handle the merging process could be considered, which can potentially reduce the overall time complexity.

java
import java.util.ArrayList;
import java.util.Collections;

// Definition for singly-linked list node.
class ListNode {
    int value;
    ListNode nextNode;
    ListNode(int x) { value = x; nextNode = null; }
}

public class Solution {
    public ListNode mergeAllLists(ListNode[] listOfLists) {
        ArrayList<Integer> elements = new ArrayList<>();
        ListNode root = new ListNode(0);
        ListNode current = root;
        for (ListNode node : listOfLists) {
            while (node != null) {
                elements.add(node.value);
                node = node.nextNode;
            }
        }
        Collections.sort(elements);
        for (int element : elements) {
            current.nextNode = new ListNode(element);
            current = current.nextNode;
        }
        return root.nextNode;
    }
}

The provided Java program is designed to merge k sorted linked lists into one single sorted linked list. The process includes three main parts:

  1. Extract all elements from the list nodes into an ArrayList:

    • Loop through each linked list represented by ListNode.
    • For each node, traverse its entire length and add all node values to an ArrayList elements.
  2. Sort the ArrayList:

    • Utilize Collections.sort() to order the extracted elements in increasing order.
  3. Create a new sorted linked list:

    • Initialize a dummy ListNode called root to stitch together the new sorted list.
    • Iterate over the sorted elements, create new nodes, and append them to the linked list starting from root.
    • Use a helper ListNode current to track and connect new nodes in sequence.

The final output is acquired by returning the linked list starting from root.nextNode, ensuring that the dummy head is excluded.

This approach leverages Java’s ArrayList and Collections utilities to handle the sorting mechanism efficiently, making it suitable for merging multiple sorted linked lists effectively.

c
int numerical_compare(const void* x, const void* y) { return (*(int*)x - *(int*)y); }
struct ListNode* mergeMultipleLists(struct ListNode** listArray, int countLists) {
    int values[10000], totalValues = 0;
    struct ListNode* start;
    struct ListNode* current;
    struct ListNode dummy = {0, NULL};
    start = &dummy;
    current = start;
    for (int i = 0; i < countLists; i++) {
        struct ListNode* temp = listArray[i];
        while (temp != NULL) {
            values[totalValues++] = temp->val;
            temp = temp->next;
        }
    }
    qsort(values, totalValues, sizeof(int), numerical_compare);
    for (int i = 0; i < totalValues; i++) {
        struct ListNode* newNode =
            (struct ListNode*)malloc(sizeof(struct ListNode));
        newNode->val = values[i];
        newNode->next = NULL;
        current->next = newNode;
        current = current->next;
    }
    return start->next;
}

The given C code defines a function to merge multiple sorted linked lists into a single sorted linked list. The code uses a straightforward approach, blending a manual combination of values followed by a sort operation for simplification. Here's a breakdown of how the solution works:

  1. The function numerical_compare serves as a comparator for the quicksort (qsort) function, helping to sort integers in ascending order.

  2. mergeMultipleLists is where the merging of the linked lists occurs. It accepts an array of ListNode pointers (listArray) and the total number of lists (countLists).

  3. Inside mergeMultipleLists, an array named values is initialized to store the integers from all the linked lists, with a potential maximum of 10,000 values to accommodate the merging process.

  4. A dummy node is used as a starting point for the resulting merged list. This dummy node simplifies list operations by eliminating the need to handle special cases for the head of the list.

  5. The function iterates through each linked list, extracting values from the nodes and storing these values in the values array.

  6. After all values are collected, the array is sorted using the qsort function, leveraging the previously defined numerical_compare function to order the array.

  7. Finally, the sorted values are iterated over, and new nodes are created for each value, linking them together to form the merged final sorted linked list. The memory for each new node is dynamically allocated.

  8. The function returns the next node after the dummy (i.e., the head of the newly merged, sorted list), effectively ignoring the dummy node.

This implementation is efficient for handling small to medium-sized lists and is particularly useful in applications where merging many lists is a common operation. However, memory management and the fixed size of the values array should be points of consideration for adapting this code for very large datasets or in a production environment.

js
function combineKLists(arrOfLists) {
    let valueList = [];
    let dummyHead = new ListNode(0);
    let current = dummyHead;
    arrOfLists.forEach((list) => {
        while (list) {
            valueList.push(list.val);
            list = list.next;
        }
    });
    valueList
        .sort((x, y) => x - y)
        .forEach((value) => {
            current.next = new ListNode(value);
            current = current.next;
        });
    return dummyHead.next;
}

The JavaScript function combineKLists described here efficiently merges multiple sorted linked lists (k sorted lists) into a single sorted linked list. The process involves the following steps:

  1. Initialize an array valueList to hold the values from all the lists.

  2. Create a dummy head node, dummyHead, to facilitate easier list manipulations and a pointer current initialized to this dummy node.

  3. Use the forEach method to traverse each linked list in the arrOfLists array:

    • Navigate through each list using a while loop.
    • Extract the value of each node and add it to the valueList.
    • Move to the next node in the list until reaching the end.
  4. Sort valueList using the JavaScript array sort function to ensure all values are in ascending order.

  5. Iterate through the sorted `valueList' and for each value:

    • Create a new linked list node using the value.
    • Append this node to the linked list starting from the dummyHead.
    • Update the current pointer to this new node.
  6. Return the next node of dummyHead to skip the initial dummy node and provide the head of the newly merged and sorted linked list.

This solution merges lists by first collecting all elements and then sorting them, which guarantees the final list is in ascending order, but may not be optimal in terms of time complexity, especially for large datasets. However, it is straightforward and utilizes built-in JavaScript methods effectively for simplicity and readability.

python
class Solution:
    def mergeKSortedLists(
        self, lists: List[Optional[ListNode]]
    ) -> Optional[ListNode]:
        extracted_values = []
        dummy_head = current = ListNode(0)
        for lst in lists:
            while lst:
                extracted_values.append(lst.val)
                lst = lst.next

        for value in sorted(extracted_values):
            current.next = ListNode(value)
            current = current.next

        return dummy_head.next

The provided Python code implements a solution to merge k sorted linked lists into a single sorted linked list. Here’s a brief summary of how the solution works:

  • Initialize an empty list, extracted_values, to collect values from all the nodes in all k lists.
  • Create a dummy head node, dummy_head, which helps in easily returning the new merged list. The current variable is used to populate the new sorted linked list.
  • Loop through each list in the collection of linked lists. In each iteration, traverse the nodes of the list using a while loop, extracting values from each node and appending them to the extracted_values list.
  • Once all the values have been extracted and stored, sort this collection of values.
  • Populate the next pointers of the newly created linked list using the sorted values. For each value in sorted(extracted_values), create a new node and make it the next node of current. The current pointer is then moved to this new node.
  • Finally, return the next node of dummy_head to omit the dummy head and receive the merged sorted linked list.

This approach effectively merges k sorted lists by first aggregating all values into a single sequence, sorting this sequence, and then creating a new sorted linked list from these values.

Comments

No comments yet.