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
思路:题目都提到归并,那我们也要归并!!!
思路a:把所有节点放到一起,重新排序。时间复杂度O(NLogN),空间复杂度O(N)。相当于重排序,没有利用部分链表已经有序这一特点。
思路b:假设共k条链表,那么把K条链表同时归并,即每次从K条链表中选出最小的节点插入。时间复杂度O(KN),空间复杂度O(1)。利用了部分有序的信息,但是,时间消耗在从K条链表中寻找最小节点上。
思路c:为了改进K条链表寻找最小节点用时,采用最小堆,将寻找时间从O(k)降到O(logK),实现上使用优先队列(priorityqueue)。时间复杂度O(NLogK),空间复杂度O(K)。因为优先队列要保存K个节点。
思路d:既然已经部分有序,那么直接对K个链表两两归并,因为归并的大前提部分有序已经成立,这样省去了最小堆的空间消耗。时间复杂度O(NLogK),空间复杂度O(1)。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public void merge(ListNode tail,ListNode[] list){//思路B
ListNode min = null;
int m = -1;
for(int i = 0 ; i < list.length ; i++){
if(list[i] == null) continue;
if(min == null || min.val > list[i].val){
min = list[i];
m = i;
}
}
if(min == null) return;
ListNode next = min.next;
min.next = null;
list[m] = next;
tail.next = min;
merge(min,list);
}
public void merge(ListNode tail,ListNode[] list,int start,int stop){//思路D
ListNode min = null;
int m = -1;
for(int i = start ; i < stop ; i++){
if(list[i] == null) continue;
if(min == null || min.val > list[i].val){
min = list[i];
m = i;
}
}
if(min == null) return;
ListNode next = min.next;
min.next = null;
list[m] = next;
tail.next = min;
merge(min,list,start,stop);
}
public ListNode mergeKLists(ListNode[] lists) {
if(lists == null ) return null;
if(lists.length == 0 ) return null;
int k = lists.length;
int step = 2;
ListNode head = new ListNode(0);
int nowIndex = 0;
int len = lists.length;
while(true){
for(int start = 0 ; start< len ; start += step){
int stop = -1;
if( start + step > len ){
stop = len;
}else{
stop = start + step;
}
merge(head,lists,start,stop);
lists[nowIndex] = head.next;
head.next = null;
nowIndex++;
}
len = nowIndex;
if(len == 1 ) break;
nowIndex = 0;
}
return lists[0];
}
}