一、题目
给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。
示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
示例 2:
输入:lists = []
输出:[]
示例 3:
输入:lists = [[]]
输出:[]
提示:
k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] 按 升序 排列
lists[i].length 的总和不超过 10^4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、代码实现
1)两两合并

如图所示,我把1、2合并,然后将合并的链表结果保存在2中,然后2、3合并···直到所有链表合并到一个链表中为止。
时间复杂度:设最常的链长为n,链有k个,第一次合并是需要O(2n),第二次是(3n),第n次则为O((k+1)n),则总时间复杂度为O(nk²)。
链表代码积累
cur=cur.next=listNodes[i];
bug积累
在最开始没有考虑特殊情况,需要加上if(lists==null||lists.length==0)return null;才能解决为空的情况
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null||lists.length==0)return null;
for(int i=1;i<lists.length;i++) {
mergeTwoLists(i,lists);
}
return lists[lists.length-1];
}
private static void mergeTwoLists(int i, ListNode[] listNodes) {
// TODO Auto-generated method stub
ListNode ans=new ListNode(-1);
ListNode cur=ans;
while(listNodes[i]!=null&&listNodes[i-1]!=null) {
if(listNodes[i-1].val<=listNodes[i].val) {
cur=cur.next=listNodes[i-1];
listNodes[i-1]=listNodes[i-1].next;
}
else {
cur=cur.next=listNodes[i];
listNodes[i]=listNodes[i].next;
}
}
cur=cur.next=listNodes[i-1]!=null?listNodes[i-1]:listNodes[i];
listNodes[i]=ans.next;
}
}
2)分治法

假设有k条链,最长的链为n。则时间复杂度为O(knlogk)
1)需要if(l>r)return null;处理特殊情况
2)位运算的优先级小于算术运算,所以正确写法应该是int mid=l+((r-l)>>2);而不是int mid=l+(r-l)>>2;
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
return merge(lists, 0, lists.length - 1);
}
private static ListNode merge(ListNode[] lists, int l, int r) {
// TODO Auto-generated method stub
if(l==r)return lists[l];
//处理特殊情况
if(l>r)return null;
//位运算符一定要注意,优先级小于算术运算符
int mid=l+((r-l)>>2);
return mergeTwo(merge(lists,l,mid),merge(lists,mid+1,r));
}
private static ListNode mergeTwo(ListNode l1, ListNode l2) {
// TODO Auto-generated method stub
ListNode head=new ListNode(-1);
ListNode cur=head;
while(l1!=null&&l2!=null) {
if(l1.val<=l2.val) {
cur=cur.next=l1;
l1=l1.next;
}
else {
cur=cur.next=l2;
l2=l2.next;
}
}
cur.next=l1!=null?l1:l2;
return head.next;
}
}
该博客讨论了如何高效地合并多个已排序的链表,提供了三种不同的方法:两两合并、分治法和使用优先队列。每种方法都分析了其时间复杂度,并给出了对应的代码实现。通过这些方法,可以将所有链表合并成一个单一的升序链表。
1703

被折叠的 条评论
为什么被折叠?



