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

 

1. 首先是最简单的方法,每次遍历lists中的所有元素,取最小的一个加入合成list。

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0) return null;
        ListNode root=new ListNode(0);
        ListNode node=root;
        while(true){
            int loc=-1;
            int min=Integer.MAX_VALUE;
            for(int i=0;i<lists.length;i++){
                if(lists[i]==null) continue;
                if(min>lists[i].val){
                    loc=i;
                    min=lists[i].val;
                }
            }
            if(loc==-1) break;
            node.next=lists[loc];
            lists[loc]=lists[loc].next;
            node=node.next;
        }
        return root.next;
    }
}

time:O(nk^2), space:O(k)

这种方法最基本,但时间复杂度高。

 

2. 使用heap,java中heap是用priorityqueue实现的,each time we change a heap value, time complexity is logk

time: O(nklogk) space: logk

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0) return null;
        ListNode head=new ListNode(0);
        PriorityQueue<ListNode> pq=new PriorityQueue<ListNode>(lists.length,comp);
        for(ListNode node:lists){
            if(node!=null) pq.offer(node);
        }
        ListNode node=head;
        while(!pq.isEmpty()){
            ListNode n=pq.poll();
            node.next=n;
            node=node.next;
            if(n.next!=null) pq.offer(n.next);
        }
        return head.next;
    }
    
    private static final Comparator<ListNode> comp=new Comparator<ListNode>(){//注意comparator的写法,这里用了匿名类anonymous class,(匿名内部类的两种实现方式:第一种,继承一个类,重写其方法;第二种,实现一个接口(可以是多个),实现其方法。)这里是实现了comparator接口,必须在创建时,作为new语句的一部分来声明它们。
        public int compare(ListNode n1, ListNode n2){
            return n1.val-n2.val;
        }
    };//注意这个分号,不要掉了,这里可以堪称新建一个instance和这个instance的类一起创建了,整个是一个语句,所以末尾要有分号
}

 

 

3. divide and conquer, like merge sort, use the dichotomy, divide the whole problem in half and half... first partition the list, than merge two list.

/**
 * 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.length==0) return null;
        return mergeKL(lists,0,lists.length-1);
    }
    public ListNode mergeKL(ListNode[] lists, int start, int end){
        if(start==end) return lists[start];
        int m=(start+end)/2;
        ListNode l1=mergeKL(lists, start, m);
        ListNode l2=mergeKL(lists, m+1, end);
        return merge(l1, l2);
    }
    public ListNode merge(ListNode l1, ListNode l2){
        ListNode head=new ListNode(0);
        ListNode node=head;
        while(l1!=null&&l2!=null){
            if(l1.val<l2.val){
                node.next=l1;
                l1=l1.next;
            }
            else{
                node.next=l2;
                l2=l2.next;
            }
            node=node.next;
        }
        if(l1==null) node.next=l2;
        else if(l2==null) node.next=l1;
        return head.next;
    }
}

 

posted on 2018-09-23 15:09  elsie12  阅读(85)  评论(0)    收藏  举报