leetcode腾讯精选练习50(13)——合并K个排序链表
题目描述
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法思路
1.暴力法
有两种暴力法,一种是将所有元素放入一个链表中,重新排序;另一种是将链表逐个合并排序,这个时间复杂度会很大,前者还不错,时间复杂度时间复杂度:O(NlogN) ,其中N 是节点的总数目。
- 遍历所有的值需花费O(N) 的时间。
- 一个稳定的排序算法花费O(NlogN) 的时间。
- 遍历同时创建新的有序链表花费O(N) 的时间。
- 优先队列
一般队列都是先进先出,最小优先队列,无论入队顺序,当前最小的元素优先出队。这里用到了STL中的数据结构,我对STL不熟悉,是该多看看了。
3.分治
循环链表两两合并,直到得到最终链表。
代码
//优先队列
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
struct cmp{bool operator()(ListNode* l1, ListNode* l2){return l1->val > l2->val;}};
ListNode* mergeKLists(vector<ListNode*>& lists){
ListNode* phead = new ListNode(0); ListNode* p = phead;
if(lists.size() == 0) return nullptr;
priority_queue<ListNode*, vector<ListNode*>, cmp> MinHeap; //STL标准库中的优先队列,cmp是比较函数,决定队列是最小优先还是最大优先
for(int i = 0;i < lists.size();i++) if(lists[i] != nullptr)MinHeap.push(lists[i]);
while(!MinHeap.empty()){
p->next = MinHeap.top();p = p->next;
if(MinHeap.top()->next != nullptr) MinHeap.push(MinHeap.top()->next);MinHeap.pop();
}
return phead->next;
}
};
//分治
public class ListNode {
int val;
ListNode next;
ListNode(int x) { val = x; }
}
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(list.lengh==0) return null;
return mergeKLists(lists,0,lists.length-1);
}
public ListNode mergeKLists(ListNode[] lists,int l,int r){
if(l==r) return lists[l];
int mid = (l+r)/2;
ListNode l1 = mergeKLists(lists, l, mid);
ListNode l2 = mergeKLists(lists, mid + 1, r);
return mergeTwoLists(l1, l2);
}
private ListNode mergeTwoLists(ListNode l1,ListNode l2){
if(l1==null) return l2;
else if(l2==null) return l1;
else if(l1.val<l2.val){
l1.next = mergeTwoLists(l1.next, l2);
return l1;
}else{
l2.next = mergeTwoLists(l1, l2.next);
return l2;
}
}
}