题目:
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出:
1->1->2->3->4->4->5->6
题解:
参考这题21. 合并两个有序链表。
①:将k个排序链表两两排序,排k-1次后最终结果就是合并后结果,时间复杂度: O(kN),其中 k 是链表的数目,总共有 N个节点在最后的链表中。空间复杂度:O(1)。代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int n=lists.length;
if(n==0||lists==null) return null;
for(int i=0;i<n-1;i++){
lists[i+1]=mergeTwoLists(lists[i],lists[i+1]);
}
return lists[n-1];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null) return l2;
if(l2==null) return l1;
ListNode l1_temp=new ListNode(0);
ListNode l2_temp=new ListNode(0);
ListNode result=new ListNode(0);
l1_temp=l1;
l2_temp=l2;
while(true){
if(l1_temp.val>=l2_temp.val){
result.next=l2_temp;
l2_temp=l2_temp.next;
}
else {
result.next=l1_temp;
l1_temp=l1_temp.next;
}
result=result.next;
if(l1_temp==null) {
result.next=l2_temp;
break;
}
if(l2_temp==null){
result.next=l1_temp;
break;
}
}
if(l1.val>=l2.val) return l2;
else return l1;
}
}
②:思考后发现其实有可以优化的地方,对k个数组合并可以采用分治法,防止合并时耗时过高:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int n=lists.length;
if(n==0||lists==null) return null;
while(n>1){
if(n%2==1) lists[n-2]=mergeTwoLists(lists[n-2],lists[n-1]);
for(int i=0;i<n/2;i++){
lists[i]=mergeTwoLists(lists[2*i],lists[2*i+1]);
}
n/=2;
}
return lists[0];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null) return l2;
if(l2==null) return l1;
ListNode l1_temp=new ListNode(0);
ListNode l2_temp=new ListNode(0);
ListNode result=new ListNode(0);
l1_temp=l1;
l2_temp=l2;
while(true){
if(l1_temp.val>=l2_temp.val){
result.next=l2_temp;
l2_temp=l2_temp.next;
}
else {
result.next=l1_temp;
l1_temp=l1_temp.next;
}
result=result.next;
if(l1_temp==null) {
result.next=l2_temp;
break;
}
if(l2_temp==null){
result.next=l1_temp;
break;
}
}
if(l1.val>=l2.val) return l2;
else return l1;
}
}
③:还有一种可以借鉴的递归分治法,但是由于递归会超时,所以只将代码分享出来,取其精华即可:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists.length==0||lists==null) return null;
return recursion(lists,0,lists.length-1);
}
public ListNode recursion(ListNode[] lists,int left,int right){
if(right==left) return lists[right];
int mid=(right+left)/2;
ListNode list1=new ListNode();
ListNode list2=new ListNode();
list1=recursion(lists,0,mid);
list2=recursion(lists,mid+1,right);
return mergeTwoLists(list1,list2);
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1==null) return l2;
if(l2==null) return l1;
ListNode l1_temp=new ListNode(0);
ListNode l2_temp=new ListNode(0);
ListNode result=new ListNode(0);
l1_temp=l1;
l2_temp=l2;
while(true){
if(l1_temp.val>=l2_temp.val){
result.next=l2_temp;
l2_temp=l2_temp.next;
}
else {
result.next=l1_temp;
l1_temp=l1_temp.next;
}
result=result.next;
if(l1_temp==null) {
result.next=l2_temp;
break;
}
if(l2_temp==null){
result.next=l1_temp;
break;
}
}
if(l1.val>=l2.val) return l2;
else return l1;
}
}
大神题解