问题
Merge
k
sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
代码
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
map<int, ListNode* >mymap;
for (int i = 0 ; i < lists.size(); i++) {
ListNode* node = lists[i];
while (node) {
ListNode* tempNode = node;
node=node->next;
ListNode *bufNode = mymap[tempNode->val];
if(bufNode)
{
tempNode->next =bufNode;
}
else
{
tempNode->next = NULL;
}
mymap[tempNode->val] = tempNode;
}
}
map<int, ListNode* >::iterator beginiter = mymap.begin();
map<int, ListNode* >::iterator enditer = mymap.end();
ListNode *returnNode = NULL;
ListNode *lastNode = NULL;
for (; beginiter != enditer; beginiter++) {
if (!beginiter->second) {
continue;
}
if (!returnNode) {
returnNode = beginiter->second;
}
if (lastNode) {
lastNode->next = beginiter->second;
}
ListNode* equalNode = beginiter->second;
while (equalNode->next) {
equalNode = equalNode->next;
}
/* equalNode is the last one */
lastNode = equalNode;
}
return returnNode;
}
};
分析
方法1(超时):两个list做merge,然后反复,一直到最后一个。(这种很容易造成时间复杂度是 n^k 次方)
方法2(超时):优化方法1,利用merge_sort的思想,切半然后做merge,主要为了防止分布的太广。(这里只是侥幸心理,其实最坏时间复杂度依然会是n^k)
方法3(上面的方法)
网上有很多方法,貌似这题的争议比较大,我也和他们的完全不一样:
解释:
1. 首先,先由map来重新排列所有的list,把相同的放到一个节点下,且链接起来。
2. 然后遍历一遍,因为我已经证明map是从小到大排列的了
《证明map从小到大传送门》,然后把list首尾链接起来就可以了。
看上去很简单,首先构建这个 map 的复杂度是 O(nklognk ), 然后遍历一遍为O(nk)。所以总的复杂度是O(nklognk).不过有浪费,空间应该是 nk(这里取决于map的实现&优化鸟,除去常数,应该也是nk).
总结
这题本来是考核链表的,最后被我做成排序了,蛮扯淡的。不过复杂度相对来说比较低了。