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;
}
}