Approach 1 : Mergesort
If we know how to merge two sorted linked list into one, we can use that as a subroutine to solve this problem:
Merge lists 2 by 2.
E.g. Give 4 lists, l1, l2, l3, l4,
- merge l1 and l4 to l1
- merge l2 and l3 to l2
- merge l1 and l2 to l1
- merge l1 and l5 to l1
- merge l2 and l4 to l2
- merge l1 and l3 to l1
- merge l1 and l2 to l1
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
int n = lists.size();
if (n==0) return NULL;
if (n==1) return lists[0];
ListNode *r=NULL;
//Pay attention to the following, this makes the total running time O(nlogk), where n is the total number of nodes.
/*each original list has been touched O(logk) times, where k is the number of lists. That said, each node has been touched O(logk) times.
Note that, for odd number of lists, as shown above, some list(s) may be touched more than logk times, but still O(logk) times.*/
int a=0, b=n-1;
while(b>0)
{
a=0;
while(a<b)
lists[a] = merge2Lists(lists[a++],lists[b--]);
}
return lists[0];
}
private:
ListNode *merge2Lists(ListNode *a, ListNode *b)
{
if (a==NULL&&b==NULL) return NULL;
ListNode *r=NULL, *prev=NULL;
if (a==NULL&&b!=NULL) return b;
if (a!=NULL&&b==NULL) return a;
ListNode dummy(-1);
dummy.next = a->val>b->val?b:a;
prev = dummy.next;
if (dummy.next==a)
a= a->next;
else
b=b->next;
while(a!=NULL&&b!=NULL)
{
if (a->val<b->val)
{
prev->next = a;
prev = a;
a=a->next;
}
else
{
prev->next=b;
prev = b;
b=b->next;
}
}
prev->next = a!=NULL?a:b;
return dummy.next;
}
};
Approach 2 : HeapSort
Another way to solve the problem is to use heapsort.
For k lists, we need to compare k head nodes to find the smallest one. Since we need sort numbers dynamically, heapsort becomes a perfect fit.
- Build up a min heap of the k head nodes of given lists.
- Take the smallest one (i.e. the head of min heap) and add its next to heap.
- Repeat until all nodes in lists have been merged into one list.
Note:
- Since ListNode doesn't have its compare method, we need to provide our own comparator and pass it in during construction time.
- If we can build up the priority queue over the given linked list, it can reduce the space complexity from O(k) to O(1).
Code:
class Solution {
public:
class Compare
{
public:
bool operator() (const ListNode * lhs, const ListNode *rhs) const
{
return (lhs->val>rhs->val);
}
};
ListNode *mergeKLists(vector<ListNode *> &lists) {
int n=lists.size();
if (n==0) return NULL;
if (n==1) return lists[0];
priority_queue<ListNode *,vector<ListNode*>, Compare> pq;
for (int i=0; i<n; i++)
{
if (lists[i]!=NULL)
pq.push(lists[i]);
}
ListNode *head=NULL, *cur=NULL;
while(!pq.empty())
{
if (head==NULL)
{
head = pq.top();
cur = head;
pq.pop();
}
else
{
cur->next = pq.top();
pq.pop();
cur = cur->next;
}
if (cur->next!=NULL)
pq.push(cur->next);
}
return head;
}
};