题目描述
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表
分治解法
因为是要合并K个有序列表,可以采用归并排序,先把第一个和第二个合并成功,合并完成的再和第三个合并。合并完成的再和第四个合并,合并完成的再和第五个合并。
合并两个有序的链表
private ListNode merge2Lists(ListNode l1,ListNode l2){
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
if(l1.val < l2.val){
l1.next = merge2Lists(l1.next,l2);
return l1;
}
l2.next = merge2Lists(l1,l2.next);
return l2;
}
然后逐一合并两个链表
class Solution{
public ListNode mergeKLists(ListNode[] lists){
ListNode res = null;
for(ListNode list : lists){
res = merge2List(res,list);
}
return res;
}
}
分治策略
如果我们每次合并的数组尽可能的短,则我们的方法可以在更快地速度合并完所有数组,因此我们将所有的链表均分,然后将均分后的链表继续均分。
class Solution{
public ListNode MergeKLists(ListNode[] lists){
return mergeKLists(lists,0,lists,length);
}
//合并左半部分和右半部分数组
private ListNode mergeKLists(lists,int i, int j){
int m = j-i;
//说明不需要合并
if(m == 0) return null;
if(m == 1) return lists[i];//无需合并直接返回
ListNode left = mergeKLists(lists, i, i+m/2);
ListNode right = mergeKLists(lists,i+m/2,j);
return mergeTwoLists(left,right);//最后把左半部分和右半部分合并即可
}
public ListNode mergeTwoLists(ListNode list1,ListNode list2){
ListNode dummy = new ListNode(); //使用哨兵节点简化代码逻辑
ListNode cur = dummy;
while(list1 != null && list2 != null){
if(list1.val < list2.val){
cur.next = list1;// 把list1加到新的链表中
list1 = list1.next;
}else {
cur.next = list2;
list2 = list2.next;
}
cur = cur.next;
}
cur.next = list1 !=null? list1 : list2;
return dummy.next;
}
}
时间复杂度是O(nlogk)的