题目描述:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
一开始就是用Merge Two Sorted Lists的做法,每次用findMinIndex来找到list中最小的node,加入到head中,时间复杂度为O(nk),超时,代码如下:
public int findMinIndex(ListNode[] list){
int minIndex=-1,minValue=Integer.MAX_VALUE,n=list.length;
for(int i=0;i<n;i++) {
if(list[i]!=null){
if(list[i].val<minValue){
minValue=list[i].val;
minIndex=i;
}
}
}
return minIndex;
}
public ListNode mergeKLists(ListNode[] lists) {
ListNode head=null,tail=null;
int minIndex;
while((minIndex=findMinIndex(lists))!=-1){
ListNode newNode=new ListNode(lists[minIndex].val);
if(head==null){
head=newNode;
tail=newNode;
}else{
tail.next=newNode;
tail=newNode;
}
lists[minIndex]=lists[minIndex].next;
}
return head;
}
后来想了一下,这个算法的毛病是如果list[i]==null,list[i]还要不停的参与比较,于是我就想将List转换成Set,每次当list[i]==null的时候将list[i]从Set中除去。但是这样又出现了一个毛病,用iterator遍历set中每一个ListNode的时候就不好改变listNode的值了。
这个题的正确解法是分治法:
public ListNode mergeKLists(ListNode[] lists) {
if(lists==null||lists.length==0)
return null;
return linkedListSort(lists,0,lists.length-1);
}
public ListNode linkedListSort(ListNode[] lists,int left,int right){
if(left == right){
return lists[left];
}
int mid = (left + right) / 2;
ListNode leftList = linkedListSort(lists,left,mid);
ListNode rightlist = linkedListSort(lists,mid+1,right);
ListNode node = mergeTwoLists(leftList,rightlist);
return node;
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode listNode = null;
if(l1==null)
return l2;
if(l2==null)
return l1;
if(l1.val<l2.val){
listNode = l1;
l1 = l1.next;
}else {
listNode = l2;
l2 = l2.next;
}
ListNode p = listNode;
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;
}else{
p.next = l1;
}
return listNode;
}
这个题还可以用堆算法来解决,但是这样要维护一个优先队列,优先队列是用最小堆来实现的,每次动态增加或者删除队列中的元素,始终保持小顶堆。
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<ListNode> heap = new PriorityQueue<ListNode>(10,new Comparator<ListNode>(){
@Override
public int compare(ListNode n1, ListNode n2)
{
return n1.val-n2.val;
}
});
for(int i=0;i<lists.length;i++)
{
ListNode node = lists[i];
if(node!=null)
{
heap.offer(node);
}
}
ListNode head = null;
ListNode pre = head;
while(heap.size()>0)
{
ListNode cur = heap.poll();
if(head == null)
{
head = cur;
pre = head;
}
else
{
pre.next = cur;
}
pre = cur;
if(cur.next!=null)
heap.offer(cur.next);
}
return head;
}