leetcode 23. 合并K个排序链表
问题描述
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
代码1(逐一比较)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
int n = lists.size();
if(n == 0)return NULL;
ListNode* ans = new ListNode(0);
ListNode* a = ans;
int i,minindex,minnum;
while(checknull(lists,n))
{
minnum = INT_MAX;
for(i = 0; i < n; i++)
{
if(lists[i] != NULL && minnum > lists[i]->val)
{
minnum = lists[i]->val;
minindex = i;
}
}
a->next = lists[minindex];
lists[minindex] = lists[minindex]->next;
a = a->next;
}
a = ans->next;
delete ans;
return a;
}
bool checknull(vector<ListNode*>& lists,int n)
{
int i;
for(i = 0; i < n; i++)
{
if(lists[i])return true;
}
return false;
}
};
结果有点难以启齿:
执行用时 :464 ms, 在所有 cpp 提交中击败了12.25%的用户
内存消耗 :10.8 MB, 在所有 cpp 提交中击败了96.16%的用户
时间复杂度为O(nk),n为链表的个数(内层循环比较),k是节点总数目(最外层循环),但空间复杂度为O(1)。
代码2(优先队列)
/**
* Definition for singly-linked list.
* 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) {
int n = lists.size();
if(n == 0)return NULL;
ListNode* ans = new ListNode(0);
ListNode* a = ans,*b;
priority_queue<ListNode*,vector<ListNode*>,cmp> pq;
for(int i = 0; i < n; i++)
{
if(lists[i])pq.push(lists[i]);
}
while(!pq.empty())
{
b = pq.top();
pq.pop();
a->next = b;
b = b->next;
a = a->next;
if(b)pq.push(b);
}
a = ans->next;
delete ans;
return a;
}
};
结果:
执行用时 :36 ms, 在所有 cpp 提交中击败了74.37%的用户
内存消耗 :11 MB, 在所有 cpp 提交中击败了89.84%的用户
因为代码一外部每循环一次内部都要比较,但比较完之后的结果下一步没有利用,优先队列则利用了这一信息,从而降低了时间复杂度。时间复杂度为:O(klog(n)),空间复杂度为O(n).其中关于priority_queue的用法参考这个网址.
代码3(分治)
结果