The problem is "Merge k sorted linked lists and return it as one sorted list. " from leetcode
1.
My solution is to use a vector to maintain the current position of each linked list, sort the vector to get the node with minimal value and insert it at the end of the merged list. Here is the code:
bool cmp(ListNode *a, ListNode *b) {
return a->val < b->val;
}
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
ListNode *dummy = new ListNode(-1);
ListNode *curr = dummy;
//init
vector<ListNode*> currNodes;
for(int i = 0; i < lists.size(); ++i){
if(lists[i] != NULL){
currNodes.push_back(lists[i]);
}
}
while(!currNodes.empty()){
sort(currNodes.begin(), currNodes.end(), cmp);
curr->next = currNodes[0];
curr = curr->next;
if(currNodes[0]->next != NULL){
currNodes.push_back(currNodes[0]->next);
}
currNodes.erase(currNodes.begin());
}
return dummy->next;
}
};
Since the time complexity of std::sort is nlog(n) and we have (n1+n2...nk) iterations, thus I suppose the total time complexity is O((n1+n2...+nk)klog(k)). But at each iteration, the size of vector currNodes
may vary so I'm a little bit confused. Can anyone confirm this?
2.
Also I saw another solution on leetcode discussion forum which use the thought of "merge sort". It merges two linked list everytime.
public class Solution {
public ListNode mergeKLists(ArrayList<ListNode> lists) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(lists.isEmpty()) return null;
if(lists.size() == 1) return lists.get(0);
int k = lists.size();
int log = (int)(Math.log(k)/Math.log(2));
log = log < Math.log(k)/Math.log(2)? log+1:log; // take ceiling
for(int i = 1; i <= log; i++){
for(int j = 0; j < lists.size(); j=j+(int)Math.pow(2,i)){
int offset = j+(int)Math.pow(2,i-1);
lists.set(j, mergeTwoLists(lists.get(j), (offset >= lists.size()? null : lists.get(offset))));
}
}
return lists.get(0);
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(l1 == null) return l2;
if(l2 == null) return l1;
ListNode head = l1.val > l2.val? l2:l1;
if(head.equals(l2)){
l2 = l1;
l1 = head;
}
while(l1.next != null && l2 != null){
if(l1.next.val > l2.val){
ListNode tmp = l1.next;
l1.next = l2;
l2 = l2.next;
l1 = l1.next;
l1.next = tmp;
}
else
l1 = l1.next;
}
if(l2 != null){
l1.next = l2;
}
return head;
}
}
I wonder what is the time complexity of this solution? Since it merges two linked lists every time, there is log(n) iterations. But the linked list gets longer (since it's merged from two linked lists) after each iteration, how to compute the time complexity at each iteration and then add them up together?
Thank you in advance :)