Leetcode-Merge k Sorted Lists
昨天师兄的同事和他一起回实验室看我们,顺便交流了一下面试的事情。他在猿题库碰到了面试题:merge K sorted arrays。我马上就联想到了Leetcode上的相似的题目,当时做的时候理解的不是很深,现在拿来再反思一下。
这道题目在分布式系统中非常常见,来自不同client的sorted list要在central server上面merge起来1。
有两种方法:1.分治法;2.堆。
分治法
最初,我是逐个list合并,像滚雪球一样,有序的list越来越长,直到与最后一个list合并后,所有的list合并成功。提交后超时。设每个list长度为
n
,由于merge的时间复杂度是
所以,我们借用归并排序的思想:将问题分解成两个子任务,即分成前后各一半的list,分别将它们排成有序的list之后,再将两个有序的list合并。这样时间复杂度满足: T(k)=T(k/2)+O(n∗k),T(k)=O(nklogk) 。
struct ListNode *mergeTwoLists(struct ListNode *l1, struct ListNode *l2)
{
if (NULL == l1)
return l2;
if (NULL == l2)
return l1;
struct ListNode *head = NULL;
if (l1->val < l2->val)
{
head = l1;
head->next = mergeTwoLists(l1->next, l2);
}
else
{
head = l2;
head->next = mergeTwoLists(l1, l2->next);
}
return head;
}
struct ListNode *mergeLists_sub(struct ListNode *lists[], int begin, int end)
{
if (begin > end)
return NULL;
if (begin == end)
return lists[begin];
int mid = (begin + end)/2;
struct ListNode *left = mergeLists_sub(lists, begin, mid);
struct ListNode *right = mergeLists_sub(lists, mid+1, end);
return mergeTwoLists(left, right);
}
struct ListNode *mergeKLists(struct ListNode *lists[], int k) {
return mergeLists_sub(lists, 0, k-1);
}
堆(优先队列)
基本思路是这样的:
1.取每个list的第一个元素构成一个最小堆(或者说优先队列),
2.重复以下步骤:
a.取出最小堆的第一个元素;(若用优先队列,直接push())
b.用a中取出的元素的所在list的下一个元素替换堆首元素,再重新使堆有序化。如果该list已经是空的话,就用无穷大代替。(若用优先队列,先pop(),如果不为空,再push进a中取出的元素的所在list的下一个元素)
复杂度同分治法。
class nodeComparison
{
//此函数要加上public。
//“>”说明是最小堆。“<”说明是最大堆
public: bool operator() (Node* n1, Node* n2)
{
return n1->val > n2->val;
}
};
Node* mergeKsortedLists(vector<Node*> &lists)
{
if (lists.empty())
return NULL;
priority_queue<Node*, vector<Node*>, nodeComparison> pq;
int sz = lists.size();
for (int i = 0; i < sz; i++)
{
if (lists[i] != NULL)
pq.push(lists[i]);
}
Node helper(0);
Node *helper_ptr = &helper;
while (!pq.empty())
{
Node *toAdd = pq.top();
pq.pop();
helper_ptr->next = toAdd;
helper_ptr = toAdd;
if (toAdd->next)
pq.push(toAdd->next);
}
return helper.next;
}
如果链表变成数组,该如何处理呢?这里的做法是把每个元素都变成一个struct node节点,存储该元素所在二维数组的位置以及下一个元素,本质上和sorted lists一样。但是如果是二维vector呢,每一维的长度可能不等,所以还得加上每个一维vector的长度。代码写得很精彩,正好可以复习一下今天写的堆排序的相关代码!!!
- Merge k Sorted Lists http://www.tuicool.com/articles/ZnuEVfJ. ↩