23. 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 <= 1 0 4 10^4 104
- 0 <= lists[i].length <= 500
- − 1 0 4 < = l i s t s [ i ] [ j ] < = 1 0 4 -10^4 <= lists[i][j] <= 10^4 −104<=lists[i][j]<=104
- lists[i] is sorted in ascending order.
- The sum of lists[i].length will not exceed 1 0 4 10^4 104.
From: LeetCode
Link: 23. Merge k Sorted Lists
Solution:
Ideas:
Main Idea:
- Divide: If you have k linked lists, split them into two groups of k/2 linked lists each.
- Conquer: Recursively merge the linked lists in each group.
- Merge: After the recursive merge, you'll have two merged lists. Now, merge these two lists into one.
This approach is akin to the merge step in "merge sort" but applied to linked lists.
Detailed Explanation:
-
mergeTwoLists Function:
This function is a basic utility to merge two individual sorted linked lists (l1 and l2). If one list is empty, it returns the other. Otherwise, it compares the current nodes' values of the two lists and selects the smaller one, then continues merging with the rest.
-
mergeKListsHelper Function:
This is the recursive function that embodies the divide-and-conquer logic:
- Base Cases:
- If start > end, there are no lists to merge, so return NULL.
- If start == end, there's only one list to consider, so return that list.
- Recursive Divide & Merge:
- Find the midpoint of the current range of linked lists (mid).
- Recursively merge the left half (from start to mid).
- Recursively merge the right half (from mid + 1 to end).
- Merge the two halves using mergeTwoLists.
- mergeKLists Function:
This is the main function which acts as an initiator. It starts the recursive merge process with the entire range of linked lists (from 0 to listsSize - 1).
Code:
c
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2) {
if (!l1) return l2;
if (!l2) return l1;
if (l1->val < l2->val) {
l1->next = mergeTwoLists(l1->next, l2);
return l1;
} else {
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
}
struct ListNode* mergeKListsHelper(struct ListNode** lists, int start, int end) {
if (start > end) return NULL;
if (start == end) return lists[start];
int mid = start + (end - start) / 2;
struct ListNode* left = mergeKListsHelper(lists, start, mid);
struct ListNode* right = mergeKListsHelper(lists, mid + 1, end);
return mergeTwoLists(left, right);
}
struct ListNode* mergeKLists(struct ListNode** lists, int listsSize) {
if (listsSize == 0) return NULL;
return mergeKListsHelper(lists, 0, listsSize - 1);
}