这一题是说要合并k个有序链表,显然可以借助合并两个有序链表来做,问题的关键是时间复杂度!
两个链表的合并操作时间复杂度为O(m + n),其中m和n为两个链表的长度,那么直观来讲,k个链表,如果我们一次将每个链表都合并到第一个链表,那么时间复杂度将是O(kn1 + (k - 1)n2 + (k - 2)n3 + ... + nk),这复杂度很高!
我们发现上述方法中l1被遍历了多达k次,这究竟是不是有必要呢?完全没有,我们完全可以两个两个的合并链表,这样时间复杂度将下降为O(logk(n1 + n2 + ... + nk)),相比于前面的方法下降了很多,如果每个链表长度相同,我们就可以发现前一种是O(k ^ 2),而后一种仅为O(logk)!
下面是代码,同样时刻牢记代码的鲁棒性!
- 注意当lists为空时,程序在最后的返回语句处会出现未定义行为(我们不能访问一个空数组里的元素),因此要先加上判断语句!
/**
* 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)
{
if(lists.empty()) return nullptr;
int sz = lists.size();
//将链表组中的链表两个两个的合并
while(sz > 1)
{
for(int i = 0; i < sz / 2; ++i)
lists[i] = merge2Lists(lists[i], lists[sz - i - 1]);
sz = (sz + 1) >> 1;
}
return lists[0];
}
private:
ListNode *merge2Lists(ListNode *l1, ListNode *l2)
{
ListNode head = ListNode(0);
ListNode *curr = &head;
while(l1 != nullptr || l2 != nullptr)
{
if(!l1) {curr->next = l2, l2 = l2->next;}
else if(!l2) {curr->next = l1, l1 = l1->next;}
else
{
l1->val < l2->val ?
(curr->next = l1, l1 = l1->next) : (curr->next = l2, l2 = l2->next);
}
curr = curr->next;
}
return head.next;
}
};
下面是运行结果: