題目:
合併 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;
}
}