23 - Merge k Sorted Lists

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

Algorithm

“big-o analysis time-complex O(NKlogK)

        public ListNode merge(ListNode[] lists, int start, int end) {

            int mid = (end - start) / 2 + start;
            ListNode leftHalf = merge(lists, start, mid);
            ListNode rightHalf = merge(lists, mid + 1, end);

heap解法:heap.offer(polled.next); 这里heap的offer()参数不能是null,因为要保证polled不是null,才能更新currentNode

            if (polled.next != null) {
                heap.offer(polled.next); // @note: offer()参数不能是null
            }

Code

MergeSort 解法

public class Merge_k_Sorted_Lists {

	public static void main(String[] args) {

		Merge_k_Sorted_Lists out = new Merge_k_Sorted_Lists();
		Solution s = out.new Solution();

		ListNode l1 = null;
		ListNode l2 = new ListNode(1);

		s.mergeKLists(new ListNode[]{l1, l2});

	}


	/**
	 * Definition for singly-linked list.
	 * public class ListNode {
	 *     int val;
	 *     ListNode next;
	 *     ListNode(int x) { val = x; }
	 * }
	 */

	// ref: https://leetcode.com/articles/merge-k-sorted-list/
    // Time complexity : O(Nlogk) where k is the number of linked lists, n is total nodes count
        // k/2 + k/4 + k/8 + ... = logK
    // Space complexity : O(1)


    // 2n * k/2 + 4n * k/4 + ... + (2^x)n * k/(2^x) = nk * x
    //    k/(2^x) = 1 -> 2^x = k -> x = log2(k)
    // 所以时间复杂度为O(nk log(k)),与方法一相同。

    public class Solution {
	    public ListNode mergeKLists(ListNode[] lists) {

	        if (lists == null || lists.length == 0) {
	            return null;
	        }

	        // same as merge sort array
	        return merge(lists, 0, lists.length - 1);
	    }

	    public ListNode merge(ListNode[] lists, int start, int end) {

	        // single list
	        if (start == end) {
	            return lists[start];
	        }

	        int mid = (end - start) / 2 + start;
	        ListNode leftHalf = merge(lists, start, mid);
	        ListNode rightHalf = merge(lists, mid + 1, end);

	        return mergeTwoLists(leftHalf, rightHalf);
	    }

	    // from previous question: 21 Merge Two Sorted Lists
        public ListNode mergeTwoLists(ListNode l1, ListNode l2) {

	        ListNode dummy = new ListNode(0);
	        ListNode current = dummy;

	        while (l1 != null || l2 != null) {
	            int v1 = (l1 == null? Integer.MAX_VALUE : l1.val);
	            int v2 = (l2 == null? Integer.MAX_VALUE : l2.val);

	            if (v1 < v2) {
	                current.next = l1;
	                l1 = l1.next;
	            } else {
	                current.next = l2;
	                l2 = l2.next;
	            }

	            current = current.next; // now current is the new end node, but still pointing to next node
	            current.next = null; // @note: key, cut this node from l1 or l2
	        }

	        return dummy.next;
	    }
	}



}

heap解法

	/*
	    heap解法

            将每个list的最小节点放入一个priority queue (min heap)中。
            之后每从queue中取出一个节点,则将该节点在其list中的下一个节点插入,
            以此类推直到全部节点都经过priority queue。

            由于priority queue的大小为始终为k,而每次插入的复杂度是log k,一共插入过nk个节点。
            时间复杂度为O(nk logk),空间复杂度为O(k)。

	 */

    class Solution_Heap {
        public ListNode mergeKLists(ListNode[] lists) {

            if (lists == null || lists.length == 0) {
                return null;
            }

            ListNode dummy = new ListNode(0);
            ListNode current = dummy;

            // put 1st of each list to heap
            PriorityQueue<ListNode> heap = new PriorityQueue<>(
                (a,b) -> a.val - b.val
            );

            //
            Arrays.stream(lists).filter(Objects::nonNull).forEach(heap::offer);

            while (heap.size() != 0) {
                ListNode polled = heap.poll();

                current.next = polled;
                current = current.next;

                if (polled.next != null) {
                    heap.offer(polled.next); // @note: heap.offer()参数不能是null
                }
            }

            return dummy.next;
        }
    }