23.合併排序N個有序鏈表
23. Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
直接合並
對每一個鏈表的的頭結點進行掃描,找出最小的節點,然後將其加入結果集裏面。然後指向該節點的指針進行後移。一直到最後面所有每一個鏈表的元素都遍歷完爲止。這樣有很多節點會被比較很多次。時間複雜度爲O(nk)。
/**
* 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;
}
ListNode first = new ListNode(0);
ListNode p = first;
while(true){
ListNode min = new ListNode(Integer.MAX_VALUE);
int j;
for(j = 0; j < lists.length; j++){
if(lists[j] != null){
min = lists[j];
break;
}
}
if(j == lists.length){
break;
}
int minIndex = j;
for(int i = j; i < lists.length; i++){
if(lists[i] == null){
continue;
}
if(lists[i].val < min.val){
min = lists[i];
minIndex = i;
}
}
p.next = min;
lists[minIndex] = lists[minIndex].next;
p = p.next;
}
return first.next;
}
}
分治法
從本體我們可以採用分而治之的策略,將複雜的問題分解爲多個簡單的小問題。,其實合併k個鏈表可以分解爲合併兩個鏈表的問題。
這裏使用了一個offset來表示偏移量。舉個例子,假如有4個鏈表,我們就先合併(1,2),(3,4) 兩組鏈表然後合併爲1,3鏈表。這個時候偏移量就爲1,意識就是鏈表和與它合併的鏈表的距離。第二步就是合併(1,3)鏈表,此時的偏移量就爲2。偏移量是以2的N次方指數增長的。當全部鏈表合成完之後,結果就是第一個鏈表。這樣操作時間複雜度爲O(nlogk)。
/**
* 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;
}
for(int offset = 1; offset < lists.length; offset *= 2){
for(int i = 0; i + offset < lists.length; i += offset * 2){
lists[i] = mergeTwoLists(lists[i],lists[i+offset]);
}
}
return lists[0];
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2){
ListNode first = new ListNode(0);
ListNode p = first;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
p.next = l1;
l1 = l1.next;
p = p.next;
} else {
p.next = l2;
l2 = l2.next;
p = p.next;
}
}
if(l1 == null){
p.next = l2;
}
if(l2 == null){
p.next = l1;
}
return first.next;
}
}