Merge k sorted
linked lists and return it as one sorted list. Analyze and describe its complexity.
本题在上一题(LeetCode 21: Merge
Two Sorted Lists)基础上再加深了一步,链表个数从两个改为K个。
此题有如下几种解法:
1、最简单的方法莫过于每次都从K个链表头中找到最小的那个元素,加入结果链表中。基于此,有人通过最小堆来简化最小元素的比较。
struct CompareListNode{ bool operator()(const ListNode*p, const ListNode* q)const{ return p->val > q->val; } }; class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { ListNode head(-1); vector<ListNode*> vec_helper; //除去空链表 for (int i=0; i<lists.size(); i++) { if (lists[i]!=NULL) vec_helper.push_back(lists[i]); } //建小堆 std::make_heap(vec_helper.begin(), vec_helper.end(), CompareListNode()); ListNode* pTail = &head; while (vec_helper.size() > 0) { //取最小的元素对应的节点 ListNode *pNode = vec_helper.front(); pTail->next= pNode; pTail = pTail->next; std::pop_heap(vec_helper.begin(), vec_helper.end(), CompareListNode()); vec_helper.pop_back(); //将该节点之后一个节点加堆中 if (pNode->next) { vec_helper.push_back(pNode->next); std::push_heap(vec_helper.begin(), vec_helper.end(), CompareListNode()); } } pTail->next = NULL; return head.next; } };
同样还有基于优先队列的算法:
ListNode* mergeKLists3(vector<ListNode*>& lists) { int length = lists.size(); ListNode head(-1); ListNode* pTail = &head; priority_queue<ListNode*, vector<ListNode*>, CompareListNode> list_queue; for (int i=0; i<length; i++) { if (lists[i]) list_queue.push(lists[i]); } while (list_queue.size() >0) { ListNode* ptmpNode = list_queue.top(); list_queue.pop(); pTail->next = ptmpNode; pTail = pTail->next; if (ptmpNode->next) list_queue.push(ptmpNode->next); } pTail->next = NULL; return head.next; }
2、每次从数组中取两个链表,将合并结果加入到链表中,反复这个过程,直到数组中只剩一个链表为止,对两个链表进行合并的代码可以复用LeetCode21的代码。
ListNode* mergeKLists2(vector<ListNode*>& lists) { int length = lists.size(); if (length == 0) return NULL; while (lists.size() >1) { ListNode* p1 = lists.front (); lists.erase(lists.begin()); ListNode* p2 = lists.front(); lists.erase(lists.begin()); lists.push_back(mergeTwoLists(p1, p2)); } return lists[0]; }
3、将数组拆分成左、右两个子数组,递归的对左、右两个子数组进行合并,再将合并得到的两个链表合并在一起。
方法3比较简洁
复用上题两个链表的合并代码,方法3的实现代码如下:
ListNode* mergeKLists(vector<ListNode*>& lists) { int length = lists.size(); if (length == 0) { return NULL; } else if(length == 1) return lists[0]; else if(length == 2) { return mergeTwoLists(lists[0], lists[1]); } vector<ListNode*> leftHalf(lists.begin(), lists.begin()+length/2); vector<ListNode*> rightHalf(lists.begin()+length/2, lists.end()); return mergeTwoLists(mergeKLists(leftHalf), mergeKLists(rightHalf)); }
时间: 2024-10-03 21:53:18