Given k sorted linked lists, merge them into a single list in increasing order.

In the previous post, we have discussed how to merge two sorted linked lists into one list. This post will merge k sorted linked lists into a single list efficiently.

 
For example,

Input:  k = 3
 
List 1: 1 —> 5 —> 7 —> NULL
List 2: 2 —> 3 —> 6 —> 9 —> NULL
List 3: 4 —> 8 —> 10 —> NULL
 
Output: 1 —> 2 —> 3 —> 4 —> 5 —> 6 —> 7 —> 8 —> 9 —> 10 —> NULL

Practice this problem

1. Naive Approach

A simple solution would be to connect all linked lists into one list (order doesn’t matter). Then use the merge sort algorithm for the linked list to sort the list in ascending order. The worst-case time complexity of this approach will be O(n.log(n)), where n is the total number of nodes present in all lists. Also, this approach does not take advantage of the fact that each list is already sorted.

2. Using Min Heap

We can easily solve this problem in O(n.log(k)) time by using a min-heap. The idea is to construct a min-heap of size k and insert each list’s first node into it. Then pop the root node (having minimum value) from the heap and insert the next node from the “same” list as the popped node. We repeat this process until the heap is exhausted.

The algorithm can be implemented as follows in C++, Java, and Python:

C++


Download  Run Code

Output:

1 —> 2 —> 3 —> 4 —> 5 —> 6 —> 7 —> 8 —> 9 —> 10 —> nullptr

Java


Download  Run Code

Output:

1 —> 2 —> 3 —> 4 —> 5 —> 6 —> 7 —> 8 —> 9 —> 10 —> null

Python


Download  Run Code

Output:

1 —> 2 —> 3 —> 4 —> 5 —> 6 —> 7 —> 8 —> 9 —> 10 —> None

The heap has size k at any point, and we pop and push exactly n times, where n is the total number of nodes. Since each pop/push operation takes O(log(k)) time, the overall time complexity of this solution is O(n.log(k)).

3. Using Divide and Conquer

The above approach reduces the time complexity to O(n.log(k)) but takes O(k) extra space for the heap. We can solve this problem in constant space using Divide and Conquer.

We already know that two linked lists can be merged in O(n) time and O(1) space (For arrays, O(n) space is required). The idea is to pair up k lists and merge each pair in linear time using the O(1) space. After the first cycle, K/2 lists are left each of size 2×N. After the second cycle, K/4 lists are left each of size 4×N and so on. Repeat the procedure until we have only one list left.

This is demonstrated below in C++, Java, and Python:

C++


Download  Run Code

Output:

1 —> 2 —> 3 —> 4 —> 5 —> 6 —> 7 —> 8 —> 9 —> 10 —> nullptr

Java


Download  Run Code

Output:

1 —> 2 —> 3 —> 4 —> 5 —> 6 —> 7 —> 8 —> 9 —> 10 —> null

Python


Download  Run Code

Output:

1 —> 2 —> 3 —> 4 —> 5 —> 6 —> 7 —> 8 —> 9 —> 10 —> None

The time complexity of the above solution is O(n.log(k)) as the outer while loop in function mergeKLists() runs O(log(k)) times, and every time we are processing n nodes.

 
Author: Aditya Goel