Merge K Sorted List Leetcode #23 题解[C++]
程序员文章站
2022-06-03 10:37:51
...
题目来源
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.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
合并k个已经排好序的列表.
解题思路
有两种思路. 第一种是先写出耳熟能详的合并两个有序链表的函数, 再利用这个函数依次合并完所有的链表. 这是我一开始的思路, 但后来我想到了第二种思路, 便想试试第二种思路:
- 按照各链表的第一个元素, 先用快速排序把这些链表顺序排好;
- 第一个链表的第一个节点即是全局最小, 把它添加到结果链表中, 同时删除这个节点;
- 如果此时第一个链表已空, 删除这条链表, 后续的链表依次前移;
- 经过2,3之后, 此时第一条链表的第一个节点已经无法保证全局最小, 由于剩下的链表头结点都是排好了的, 用二分查找找出第一条链表的第一个节点所应放的正确位置, 直接把第一条链表移到该位置;
- 还有链表非空时, 重复2,3,4; 直至返回最终的合并链表.
复杂度分析
结合下面的代码, 假设n条长为m的链表, 第一次遍历去掉空链表是O(n), 之后一次快排是O(nlogn), 之后需要进行O(n*m)次操作把全部节点加入到最终链表中, 每一次都需要进行一次O(logn)的二分查找, 所以最终复杂度是O(nm log n).
比起来实际上第一种思路应该会快一些, 因为第二种思路实现的代码看起来速度相当一般. 如下图.
代码实现
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
for (int count = 0; count < lists.size();) {
if (lists[count] == nullptr) lists.erase(lists.begin() + count);
else count++;
}
if (lists.empty()) return nullptr;
ListNode combine(0);
ListNode* last_sorted = &combine;
quickSort(0, lists.size() - 1, lists);
while (!lists.empty()) {
last_sorted->next = lists[0];
last_sorted = last_sorted->next;
lists[0] = lists[0]->next;
if (lists[0] == nullptr) {
lists.erase(lists.begin());
continue;
}
int idx = binarySearch(1, lists.size() - 1, lists[0]->val, lists);
lists.insert(lists.begin() + idx, lists[0]);
lists.erase(lists.begin());
}
return combine.next;
}
int binarySearch(int left, int right, int key, vector<ListNode*> & lists) {
int lo = left;
int hi = right;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (key <= lists[mid]->val) {
hi = mid - 1;
}
else lo = mid + 1;
}
return lo;
}
int partition(int left, int right, vector<ListNode*>& lists) {
int lo = left;
int hi = right;
int pivot = lists[hi]->val;
for (int k = lo; k < hi; k++) {
if (lists[k]->val < pivot) {
swap(lists[k], lists[lo++]);
}
}
swap(lists[lo], lists[hi]);
return lo;
}
void quickSort(int left, int right, vector<ListNode*>& lists) {
if (left >= right) return;
int idx = partition(left, right, lists);
quickSort(left, idx - 1, lists);
quickSort(idx + 1, right, lists);
}
};
下一篇: 『算法』general