问题描述
合并 k 个已排序的链表并将其作为一个已排序的链表返回。分析并描述其复杂度。
输入描述:
输入一个链表的集合
输出描述:
输出合并后的链表
示例
示例1
输入
[{1,2,3},{4,5,6,7}]
输出
{1,2,3,4,5,6,7}
解决思路
分析
- 通过顺序合并的方式,先合并前两个链表,然后以合并后的链表一次与后面每一个链表合并(这种方式会花费额外的时间,这里不做介绍)
- 通过二分分组的方式,对链表分组,分 k/2 组,对每组的两个链表进行合并,取合并后的链表再进行分组,重复这个过程
- 通过优先队列的方式,通过维护每个链表的首元素,依次弹出追加元素(后期会补充代码)
方法
- 通过对链表进行二分分组的方式实现排序
代码实现
// 思路1
public class Solution {
public ListNode merge(ArrayList<ListNode> lists, int l, int r) {
if (l == r) {
return lists.get(l);
}
if (l > r) {
return null;
}
int mid = (l + r) >> 1;
return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
}
private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if (l1 == null || l2 == null) {
return l1 == null ? l2 : l1;
}
ListNode dummy = new ListNode(0);
ListNode temp = dummy;
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
temp.next = l1;
l1 = l1.next;
} else {
temp.next = l2;
l2 = l2.next;
}
temp = temp.next;
}
if (l1 != null) temp.next = l1;
if (l2 != null) temp.next = l2;
return dummy.next;
}
}
时间复杂度分析:
第一次分组:k/2个组,每组合并需要的时间复杂度为2个链表的长度和,假设最长为n,则每组合并的时间复杂度为O(2n),总的时间复杂度为:O(k/2 * 2n) = O(kn)
第二次分组:k/4个组,每组合并需要的时间复杂度为4个链表的长度和 O(4n) 【注意:这里承接了第一组,所以长度会*2】,总的时间复杂度为:O(k/4 * 4n) = O(kn)
第logk次分区,相同,因为采用了二分的方法分组,所以k组分组的总共次数为logk次,所以总的时间复杂度为O(logk * kn)
空间复杂度分析:
因为采用递归的方式,没有申请额外的空间存储,所以空间复杂度为O(1)
小伙伴如果想测试的话,可以直接到牛客网这个链接做测试