Skip to main content

Merge k Sorted Lists


Merge k Sorted Lists: You are given an array of k linked-lists lists, each linked-list is sorted in ascending order.

Merge all the linked-lists into one sorted linked-list and return it.

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 <= 10^4
  • 0 <= lists[i].length <= 500
  • -10^4 <= lists[i][j] <= 10^4
  • lists[i] is sorted in ascending order.
  • The sum of lists[i].length will not exceed 10^4.

Try this Problem on your own or check similar problems:

  1. Merge Two Sorted Lists
  2. Ugly Number II
  3. Smallest Subarrays With Maximum Bitwise OR
Solution:
public ListNode mergeKLists(ListNode[] lists) {
ListNode dummy = new ListNode(-1, null), iter = dummy;
PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);

for(int i = 0; i < lists.length; ++i){
if(lists[i] != null) pq.add(lists[i]);
}

while(!pq.isEmpty()){
ListNode node = pq.poll();
iter.next = node;
if(node.next != null){
pq.add(node.next);
}
iter = iter.next;
}

return dummy.next;
}

Time/Space Complexity:
  • Time Complexity: O(nlogk) where k is the number of lists
  • Space Complexity: O(k)

Explanation:

For the time complexity we have O(nlogk) where logk is needed for polling and inserting a node in the queue of maximum size k (the maximum size is determined by the number of lists, since the queue will be the longest after the first loop once we have placed head nodes of each list), while n is the total number of nodes in the merged list (sum of lengths of all linked lists). For space complexity we have the queue of maximum size k. We solve the problem by using minheap and first inserting all heads of all lists as our first candidates. We then keep on polling until there is no element left in the queue, which means we have merged all the nodes from all lists. When we poll a node, we know it's the node with the smallest value, so it makes sense to insert the next (if there is one) element from the linked list inserted node is coming from, back in the queue. Each iteration we will be polling the smallest value node and end up with sorted merged list. This problem can be solved without any additional space complexity if we utilized the algorithm for Merge Two Sorted Lists where we merge bigger and bigger parts of the lists until we reach point where we're merging only two sorted lists:

class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length == 0){
return null;
}

int interval = 1;
while(interval < lists.length){
for (int i = 0; i + interval < lists.length; i = i + interval * 2) {
lists[i] = mergeTwoLists(lists[i], lists[i + interval]);
}
interval *= 2;
}

return lists[0];
}

private ListNode mergeTwoLists(ListNode list1, ListNode list2) {
if(list1 == null || list2 == null) return list1 == null ? list2 : list1;

ListNode dummy = new ListNode(-1, null), curr = dummy;

while(list1 != null && list2 != null){
if(list1.val < list2.val){
curr.next = list1;
list1 = list1.next;
}
else{
curr.next = list2;
list2 = list2.next;
}

curr = curr.next;
}

if(list1 != null || list2 != null){
curr.next = list1 != null ? list1 : list2;
}

return dummy.next;
}
}

We keep on doubling the interval, so for the first iteration we will be merging lists in pairs, and we will end up with n/2 lists which we will then merge to get n/4 lists until there is only list left. It takes at most n nodes to merge the last two halves, and we have log n lists (each time halving the total number of lists) leading to O(nlogn) time complexity. Note again that n is the total number of nodes in all lists.