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