题目:
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
思路1:
和普通的两个有序数组排序的方法类似,每次选出n个链表当前所指元素中的最小值加入新的链表,直到所有链表都遍历完成。
时间复杂度O(n^2)
代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode lr = new ListNode(0);
ListNode r = lr;
int min,minindex=-1;
while(true){
int count = lists.length;
min = Integer.MAX_VALUE;
for(int i=0;i<lists.length;i++){
if(lists[i]==null){
count--;
continue;
}
if(lists[i].val<min){
min = lists[i].val;
minindex = i;
}
}
if(count==0){
//r所指的节点置为空
return lr.next;
}
r.next = new ListNode(min);
lists[minindex] = lists[minindex].next;
r = r.next;
}
}
}
思路2:
分支策略
若不太理解分治可类比折半查找算法。将整个链表数组分割从中间分割成两个数组,对子数组进行同样的分割操作。直到分割为单个的链表时,两两合并链表。
时间复杂度O(n logn)
参考博客:https://blog.csdn.net/qq_43322057/article/details/83987412
代码:
/**
* 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==null||lists.length==0) return null;
return merge(lists,0,lists.length-1);
}
//类似二叉树模型,从叶子节点向上合并各个链表
public ListNode merge(ListNode[] lists,int begin,int end){
if(begin<end){
int mid = (begin+end)/2;
ListNode l = merge(lists,begin,mid);
ListNode r = merge(lists,mid+1,end);
return combine2List(l,r);
}
return lists[begin];
}
public ListNode combine2List(ListNode l1,ListNode l2){
ListNode r;
if(l1==null) return l2;
if(l2==null) return l1;
if(l1.val>l2.val){
r = l2;
r.next = combine2List(l1,l2.next);
}else{
r = l1;
r.next = combine2List(l1.next,l2);
}
return r;
}
}