leetcode23- Merge k Sorted Lists- hard

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

private Comparator<ListNode> listComparator = new Comparator<ListNode>(){

算法:

1. 用heap(priorityQueue)。维护一个最小堆,记录每一串ListNode当前指着的那k个(或者更少)ListNode,每次取出来直接是最小的那个。然后把取出来的这个后面的加回heap里。 每次取出小的后就可以直接连到长串上面了。

2.自上向下的类似mergeSort的分治法。写一个分治,每次把合并任务分成合并左边一半与合并右边一半,这是分。再重写一遍原来的merge two lists,这是合,类似于原来的merge。递归调用就好了。

3.自下而上的归并法。从一共k条链表开始,从左到右一条条两两合并,最后落单的话不合并,把这些新的链表作为向上一层的新的要处理的链表点。一直向上一直向上,直到合并成只有一个点的一条就可以输出了。

时间复杂度:都是Nlogk。N是所有节点个数,k是有链表条数。堆的话因为堆的深度是logK。分治法和归并法的话是因为长出来的树高度是logK。

细节: 1.用heap的话要实现Comparator<ListNode>。实现的写法多看几次下面的。实现细节太多了

a)记得写完内部类后要加;(因为前面是在赋值)

b)记得实现内部类的时候<>里不可以省略。

c)记得compare()这个方法全小写

d)记得return回去的int按传入参数顺序顺着来就是维护从小到大的堆。

e)记得初始化heap的时候可以传入两个参数,第一个大小,第二个比较器。大小的值必须>=1!Queue<ListNode> heap = new PriorityQueue<ListNode>(lists.length, listComparator);

f)heap不可以add(null)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    
    // 切记前面等号右边<>里不可以省略,然后最后要加个分号
    private Comparator<ListNode> listComparator = new Comparator<ListNode>(){
        // 切记方法名都是小写
        public int compare(ListNode l1, ListNode l2) {
            return l1.val - l2.val;
        }
    };
        
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        
        ListNode dummy = new ListNode(0);
        ListNode prev = dummy;
        // 注意,java API里面要求初始化大小不能<1。所以要注意对lists.length = 0 的情况限定
        
        Queue<ListNode> heap = new PriorityQueue<ListNode>(lists.length, listComparator);
        for (int i = 0; i < lists.length; i++) {
            // heap不能add(null)
            if (lists[i] != null) {
                heap.add(lists[i]);       
            }
        }
        
        while (!heap.isEmpty()) {
            ListNode crt = heap.remove();
            if (crt.next != null) {
                heap.add(crt.next);
            }
            prev.next = crt;
            prev = prev.next;
        }
        return dummy.next;
    }
}

2.分治法

/**
 * 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;
        }
        return recursiveHelper(lists, 0, lists.length - 1);
        
    }
    
    private ListNode recursiveHelper(ListNode[] lists, int start, int end) {
        
        if (start == end) {
            return lists[start];
        }
        
        int mid = start + (end - start) / 2;
        ListNode left = recursiveHelper(lists, start, mid);
        ListNode right = recursiveHelper(lists, mid + 1, end);
        return merge2List(left, right);
    }
    
    private ListNode merge2List(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode prev = dummy;
        
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                prev.next = l1;                
                l1 = l1.next;
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }
        if (l1 != null) {
            prev.next = l1;
        }
        if (l2 != null) {
            prev.next = l2;
        }
        return dummy.next;
    }
    
}

3.归并法

/**
 * 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;
        }
        
        List<ListNode> list = new ArrayList<>();
        for (int i = 0; i < lists.length; i++) {
            if (lists[i] != null) {
                list.add(lists[i]);
            }
        }
        
        if (list.size() == 0) {
            return null;
        }
        
        while (list.size() > 1) {
            List<ListNode> newList = new ArrayList<>();
            for (int i = 0; i + 1 < list.size(); i += 2) {
                newList.add(merge2List(list.get(i), list.get(i + 1)));
            }
            if (list.size() % 2 == 1) {
                newList.add(list.get(list.size() - 1));
            }
            list = newList;
        }

        return list.get(0);

    }
    
    
    
    private ListNode merge2List(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(0);
        ListNode prev = dummy;
        
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                prev.next = l1;                
                l1 = l1.next;
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            prev = prev.next;
        }
        if (l1 != null) {
            prev.next = l1;
        }
        if (l2 != null) {
            prev.next = l2;
        }
        return dummy.next;
    }
    
}
原文地址:https://www.cnblogs.com/jasminemzy/p/7812744.html