23.合并K个有序链表
合并k个有序链表
我们首先把k个链表的首元素都加入最小堆中,它们会自动排好序。
然后我们每次取出最小的那个元素加入我们最终结果的链表中,
然后把取出元素的 下一个元素 再加入堆中,下次仍从堆中取出最小的元素做相同的操作,
以此类推,直到堆中没有元素了,此时k个链表也合并为了一个链表,返回首节点即可,代码如下:
方法一,利用堆的性质
class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { auto cmp = [](ListNode*& a, ListNode*& b) { return a->val > b->val; }; priority_queue<ListNode*, vector<ListNode*>, decltype(cmp) > q(cmp); for (auto node : lists) { if (node) q.push(node); } ListNode *dummy = new ListNode(-1), *cur = dummy; while (!q.empty()) { auto t = q.top(); q.pop(); cur->next = t; cur = cur->next; if (cur->next) q.push(cur->next); } return dummy->next; } };
方法2 分治法, 归并排序,既然是有k个有序的链表,则不难想到归并 class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { if(lists.empty()) return NULL; return helper(lists, 0, (int)lists.size() - 1);//既然k个有序链表都是有序的,我们对他们归并排序 } ListNode* helper(vector<ListNode*>& lists, int start, int end) { //先调用递归函数,将区间分割到最小 if (start == end) return lists[start]; //递归到只有一个的时候,直接返回该链表 int mid = start + (end - start) / 2; ListNode *left = helper(lists, start, mid);//向左半边递归 ,left为左边归并的结果 ListNode *right = helper(lists, mid + 1, end);//向右半边递归 ,right为右边归并的结果 return mergeTwoLists(left, right); //合并左右归并结果,返回合并后的有序链表 } ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { //合并两个有序链表 ListNode *dummy = new ListNode(-1); ListNode *t = dummy; ListNode *p,*q; p = l1; q = l2; while(p&&q) { if(p->val <= q->val) { t->next = p; p=p->next; t = t->next; } else { t->next = q; q = q->next; t = t->next; } } if(q) { t->next = q; } if(p) { t->next =p; } return dummy->next; } };

浙公网安备 33010602011771号