Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
这一道题目其实就是k路归并,十分经典的问题。这个可以说是大数据相关或后台面试经常问到的问题。当初面企鹅面到类似的问题没有答上来,技术渣渣啊。。。
思路一:分别进行两两归并,直至最后合为一条链表
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1,ListNode* l2)
{
if(l1 == NULL)
return l2;
if(l2 == NULL)
return l1;
if(l1->val < l2->val)
{
l1->next = mergeTwoLists(l1->next,l2);
return l1;
}
else
{
l2->next = mergeTwoLists(l1,l2->next);
return l2;
}
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.empty())
return NULL;
if(lists.size() == 1)
return lists[0];
while(lists.size() > 1)
{
lists.push_back(mergeTwoLists(lists[0],lists[1]));
lists.erase(lists.begin());
lists.erase(lists.begin());
}
return lists[0];
}
};
思路二:思路一中在进行每个链表的元素比较时,采用过的是线性比较,而且采用的递归,随着递归层次的增加效率受影响比较严重。思路二在这一方面进行优化,通过最小堆,使得每次查找最小元素的时间由O(N)变为O(logN)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
static bool heapComp(ListNode* a, ListNode* b) {
return a->val > b->val;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
ListNode head(0);
ListNode* curr= &head;
vector<ListNode*> v;
for(int i=0;i<lists.size();i++)
{
if(lists[i])
v.push_back(lists[i]);
}
make_heap(v.begin(),v.end(),heapComp);
while(v.size() > 0)
{
curr->next = v.front();
pop_heap(v.begin(),v.end(),heapComp);
v.pop_back();
curr = curr->next;
if(curr->next)
{
v.push_back(curr->next);
push_heap(v.begin(),v.end(),heapComp);
}
}
return head.next;
}
};
虽然使用过STL,但是对heap的使用不是很熟悉
思路三:可以将思路二中的heap换为priority_queue,整个解法基本一致
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
struct compare {
bool operator()(const ListNode* l, const ListNode* r) {
return l->val > r->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode *, vector<ListNode *>, compare> q;
for(int i=0;i<lists.size();i++)
{
if(lists[i])
q.push(lists[i]);
}
ListNode head(0);
ListNode* curr = &head;
while(q.size() > 0)
{
curr->next = q.top();
curr = curr->next;
q.pop();
if(curr->next)
q.push(curr->next);
}
return head.next;
}
};
需要想办法找到如何更高效的解决该问题