题目:
https://leetcode.com/problems/merge-k-sorted-lists/description/
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Difficulty: Hard
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
即归并多个有序数列。
分析:
首先,想象归并两个有序数列的情形:
指针p1处于数列1的开头,指针p2处于数列2的开头。
要将数列2并入数列1中,则:
①如果p2的值<=p1的值,则移动p2,直到p2为空或p2的值>p1的值;
②否则,即p2的值>p1的值,或p1已到达数列1的结尾,这样就可以确定要把数列2的什么区间插入到数列1的p1处。
区间插入后,p1移动一位,重复以上步骤直到归并完毕。
类似于下图:
然后,采用分治法,不断两个两个地归并数列,归并的结果又继续进行两路归并,直到只有一个已排好序的数列。
算法如下:
class Solution {
public:
ListNode* merge(ListNode* l1, ListNode* l2){ // 归并两个有序数列
ListNode tmp(0);
ListNode* result = &tmp;
result->next = l1;
ListNode* head = l2;
if(l1 == NULL && l2 != NULL){
return l2;
}
else if(l2 == NULL){
return l1;
}
ListNode* p1 = result->next;
ListNode* p2 = head;
ListNode* pre = result;
while(p1 != NULL && p2 != NULL){
if(p2->val <= p1->val) {
ListNode* first = p2;
while(p2->next != NULL && p2->next->val <= p1->val){
p2 = p2->next;
}
ListNode* last = p2;
p2 = p2->next;
pre->next = first;
last->next = p1;
}
pre = p1;
p1 = p1->next;
}
if(p1 == NULL && p2 != NULL){
pre->next = p2;
}
return result->next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) { // 归并多个有序数列
if(lists.size() == 0) return NULL;
while(lists.size() > 1){
int size = lists.size();
int n = size / 2;
for(int i = 0; i < n; i++){
ListNode* node = merge(lists[2 * i], lists[2 * i + 1]);
lists.push_back(node);
}
lists.erase(lists.begin(), lists.begin() + 2 * n);
}
return lists[0];
}
};
时间复杂度为 O ( n ⋅ l o g k ) O(n·logk) O(n⋅logk)。其中n为所有的数字的个数,k为数列的个数。
用时为20ms。