合并K个排序链表
今天是一道难度为hard的题目,来自leetcode,但是通过率并不低,Acceptance为51.7%。
题目如下
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/me… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
回复0000查看更多题目
解题思路
思路一
初看该题似乎并不难,因为链表都是有序的,假设有K个链表,取K 个指针分别指向 K条链表,并从逐个链表头取数据并比较,取最小的插入新的链表,然后指针后移;直到每个链表都到结尾就能得到最后的结果。考虑一下这种算法的时间复杂度。
假设所有链表的元素总数和是N,因为有K个链表,每次都是比较K词,所以总的时间复杂度是O(KN)。
代码如下
Java版
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int k = lists.length;
ListNode dummyHead = new ListNode(0);
ListNode tail = dummyHead;
while (true) {
ListNode minNode = null;
int minPointer = -1;
for (int i = 0; i < k; i++) {
if (lists[i] == null) {
continue;
}
if (minNode == null || lists[i].val < minNode.val) {
minNode = lists[i];
minPointer = i;
}
}
if (minPointer == -1) {
break;
}
tail.next = minNode;
tail = tail.next;
lists[minPointer] = lists[minPointer].next;
}
return dummyHead.next;
}
}
思路二
考虑上面的思路有没有优化空间,因为每次取K个值都需要重新比较,仔细思考这里只有1个值是新的,另外的K-1个值已经比较过是有序了,那么只需要比较这个新的值就可以了。如何实现呢?
可以使用小根堆进行优化,用一个小跟堆维护比较比较过的K-1个值,这样每次比较 K个指针求 min只需要 O(logK)次比较, 时间复杂度:O(NlogK)。
Java版
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
Queue<ListNode> pq = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);
for (ListNode node: lists) {
if (node != null) {
pq.offer(node);
}
}
ListNode dummyHead = new ListNode(0);
ListNode tail = dummyHead;
while (!pq.isEmpty()) {
ListNode minNode = pq.poll();
tail.next = minNode;
tail = minNode;
if (minNode.next != null) {
pq.offer(minNode.next);
}
}
return dummyHead.next;
}
}
关注我
回复0000查看更多题目
