▶ 合并 k 个已经排好序的单链表
● 代码,28 ms,二路归并递归版,时间复杂度 O(k n log k)
1 class Solution 2 { 3 public: 4 ListNode *mergeTwoLists(ListNode* l1, ListNode* l2) 5 { 6 if (l1 == nullptr) 7 return l2; 8 if (l2==nullptr) 9 return l1; 10 if (l1->val <= l2->val) 11 { 12 l1->next = mergeTwoLists(l1->next, l2); 13 return l1; 14 } 15 else 16 { 17 l2->next = mergeTwoLists(l1, l2->next); 18 return l2; 19 } 20 } 21 ListNode *mergeKLists(vector<ListNode *> &lists) 22 { 23 if (lists.empty()) 24 return nullptr; 25 int i, len; 26 for (len = lists.size(); len > 1; len = (len + 1) / 2) 27 { 28 for (i = 0; i < len / 2; i++) 29 lists[i] = mergeTwoLists(lists[i], lists[len - 1 - i]); 30 } 31 return lists.front(); 32 } 33 };
● 代码,30 ms,二路归并非递归版,时间复杂度 O(k n log k)
1 class Solution 2 { 3 public: 4 ListNode *mergeTwoLists(ListNode* l1, ListNode* l2) 5 { 6 ListNode dummy(-1), *result = &dummy; 7 for(;l1!=nullptr &&l2!=nullptr;) 8 { 9 if (l1->val <= l2->val) 10 { 11 result->next = l1; 12 l1 = l1->next; 13 } 14 else 15 { 16 result->next = l2; 17 l2 = l2->next; 18 } 19 result = result->next; 20 } 21 if (l1) 22 result->next = l1; 23 else if (l2) 24 result->next = l2; 25 return dummy.next; 26 } 27 ListNode *mergeKLists(vector<ListNode *> &lists) 28 { 29 if (lists.empty()) 30 return NULL; 31 int i, len; 32 for (len = lists.size(); len > 1; len = (len + 1) / 2) 33 { 34 for (i = 0; i < len / 2; i++) 35 lists[i] = mergeTwoLists(lists[i], lists[len - 1 - i]); 36 } 37 return lists.front(); 38 } 39 };
● 代码,29 ms,优先队列,最快的解法算法与之相同,时间复杂度 O(N log k)
1 class Solution 2 { 3 public: 4 struct compare 5 { 6 bool operator()(const ListNode* l, const ListNode* r) 7 { 8 return l->val > r->val; 9 } 10 }; 11 ListNode *mergeKLists(vector<ListNode *> &lists) 12 { 13 priority_queue<ListNode *, vector<ListNode *>, compare> q; 14 ListNode *result, *tail; 15 for (auto l : lists) // 把各单链表首元素加入优先队中 16 { 17 if (l) 18 q.push(l); 19 } 20 if (q.empty()) 21 return NULL; 22 result = q.top(), q.pop(); // 取出头部 23 if (result->next) 24 q.push(result->next); 25 for (tail = result; !q.empty();) 26 { 27 tail->next = q.top(), q.pop();// 每次取出一个元素,若取出的元素有后继,则将后继加入优先队中 28 tail = tail->next; 29 if (tail->next) 30 q.push(tail->next); 31 } 32 return result; 33 } 34 };
● 代码,29 ms,使用堆,时间复杂度 O(N log k)
1 class Solution 2 { 3 public: 4 static bool heapComp(ListNode* a, ListNode* b) 5 { 6 return a->val > b->val; 7 } 8 ListNode* mergeKLists(vector<ListNode*>& lists) 9 { 10 ListNode head(0); 11 ListNode *curNode = &head; 12 vector<ListNode*> v; 13 for (int i = 0; i<lists.size(); i++) 14 { 15 if (lists[i]) 16 v.push_back(lists[i]); 17 } 18 make_heap(v.begin(), v.end(), heapComp);// 建堆 19 for (;v.size()>0;) 20 { 21 curNode->next = v.front(); 22 pop_heap(v.begin(), v.end(), heapComp); 23 v.pop_back(); 24 curNode = curNode->next; 25 if (curNode->next) 26 { 27 v.push_back(curNode->next); 28 push_heap(v.begin(), v.end(), heapComp); 29 } 30 } 31 return head.next; 32 } 33 };