题目
描述
合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。
数据范围:节点总数 0≤n≤5000,每个节点的 val 满足 ∣val∣<=1000
要求:时间复杂度 O(nlogn)
示例 1
输入:[{1,2,3},{4,5,6,7}]返回值:{1,2,3,4,5,6,7}
复制代码
示例 2
输入:[{1,2},{1,4,5},{6}]返回值:{1,1,2,4,5,6}
复制代码
分析
考虑特殊情况
在进行问题分析过程前,我们先考虑一下特殊情况,那么在这道问题中,有哪些情况是特殊的呢?
不难发现,如下情况:
考虑一般情况
其实这个问题是合并两个链表的问题衍生,我们之前学习了如何合并两个有序链表,那么我们可以将这个问题进行拆解。
第一种思路,也是最容易想到的思路,对所有链表依次进行合并:
先合并第一个,第二个,得到合并后的链表;然后使用该链表来和第三个链表进行合并,依次进行。
我们假设有 n 个链表,每两个链表合并平均需要遍历 m 次,那么我们的时间复杂度就大致应该是 O(mn);
第二种思路,我们也是基于两个两个链表合并的函数,对我们拥有的 n 个链表进行拆解:
分为前半部分的链表和后半部分的链表,那最终的结果实际上是合并这两部分链表的结果;
前半部分和后半部分其实是我们的子问题,可以归并的方式获取;
最后的停止条件是我们的子区间为空返回空指针或者只有一个链表,返回该链表。
使用归并的方法就可以将使用两个链表合并操作的次数下降到 O(logn),可以满足题目的要求。
代码示例
版本一
注意:这里 pReturn 首先赋值为 lists[0],进行比较时从 lists[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) { if(lists.size() == 0){ return nullptr; } if(lists.size() == 1){ return lists[0]; } ListNode* pReturn = lists[0]; for(size_t i = 1;i < lists.size();++i){ pReturn = merge2Lists(pReturn, lists[i]); } return pReturn; } ListNode* merge2Lists(ListNode* pHead1, ListNode* pHead2) { // special condition if (nullptr == pHead1) { return pHead2; }
if (nullptr == pHead2) { return pHead1; }
ListNode* pReturn = nullptr; ListNode* pCur0 = nullptr; ListNode* pCur1 = pHead1; ListNode* pCur2 = pHead2;
// assign the pReturn if (pHead1->val <= pHead2->val) { pReturn = pHead1; pCur1 = pCur1->next; } else { pReturn = pHead2; pCur2 = pCur2->next; } pCur0 = pReturn;
// traverse the two list and link them while (nullptr != pCur1 && nullptr != pCur2) { if (pCur1->val <= pCur2->val) { pCur0->next = pCur1; pCur1 = pCur1->next; } else { pCur0->next = pCur2; pCur2 = pCur2->next; } pCur0 = pCur0->next; }
if (nullptr == pCur1) { pCur0->next = pCur2; } else if (nullptr == pCur2) { pCur0->next = pCur1; }
return pReturn; }};
复制代码
版本二
注意这里的终止条件:
left > right:返回 nullptr
left == right:返回 lists[left]
class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { if(lists.size() == 0){ return nullptr; } if(lists.size() == 1){ return lists[0]; } return divideMerge(lists, 0, lists.size() - 1); } ListNode* divideMerge(vector<ListNode*>& lists,int left, int right){ if(left > right){ return nullptr; }else if(left == right){ return lists[left]; } int mid = (left+right)/2; return merge2Lists(divideMerge(lists, left, mid), divideMerge(lists, mid+1, right)); } ListNode* merge2Lists(ListNode* pHead1, ListNode* pHead2) { ...// 实现同1 }};
复制代码
评论