Sunday, January 8, 2017

Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example
Given lists:
[
  2->4->null,
  null,
  -1->null
],
return -1->2->4->null.


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

/*
First put all the ListNode in the input array into the min-heap. Every time,  pop out the ListNode with the smallest value. If this ListNode's next node is not null, then push the next ListNode into the min-heap. 

PriorityQueue. time: O(NlogK), space: O(K), N: the number of all the ListNode,K: the length of the input lists array.
*/

public class Solution {
    private Comparator<ListNode> ListNodeComparator = new                                                Comparator<ListNode>() {
        public int compare(ListNode a, ListNode b) {
            return a.val - b.val;    //b.val-a.val, descending sort.
        }
    };
    public ListNode mergeKLists(ListNode[] lists) {  
        if (lists == null || lists.length == 0) {
            return null;
        }
        Queue<ListNode> heap = new PriorityQueue<>(lists.length,                                                   ListNodeComparator); 
        for (ListNode node : lists) {
            if (node != null) {
                heap.offer(node); 
            }
        }
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
        while (!heap.isEmpty()) {
            ListNode head = heap.poll();
            tail.next = head;
            tail = head;
            if (head.next != null) {
                heap.offer(head.next);
            }
        }
        return dummy.next;
    }
}


//divide & conquer, recursion, time: O(NlogK), space: O(1)
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        return mergeHelper(lists, 0, lists.length - 1);
    }
    public ListNode mergeHelper(ListNode[] lists, int start, int end) {
        if (start == end) {
            return lists[start];
        }
        int mid = start + (end - start) / 2;
        ListNode left = mergeHelper(lists, start, mid);
        ListNode right = mergeHelper(lists, mid + 1, end);
        
        return mergeTwoLists(left, right);
    }
    private ListNode mergeTwoLists(ListNode head1, ListNode head2) {
        ListNode dummy = new ListNode(0);
        ListNode temp = dummy;
        while (head1 != null && head2 != null) {
            if (head1.val < head2.val) {
                temp.next = head1;
                head1 = head1.next;
            } else {
                temp.next = head2;
                head2 = head2.next;
            }
            temp = temp.next;
        }
        if (head1 != null) {
            temp.next = head1;
        } else {
            temp.next = head2;
        }
        return dummy.next;
    }
}


//merge two by two, iteration, time: O(NlogK), space: O(K)
public class Solution {
    private ListNode mergeTwoLists(ListNode head1, ListNode head2) {
        ListNode dummy = new ListNode(0);
        ListNode temp = dummy;
        while (head1 != null && head2 != null) {
            if (head1.val < head2.val) {
                temp.next = head1;
                head1 = head1.next;
            } else {
                temp.next = head2;
                head2 = head2.next;
            }
            temp = temp.next;
        }
        if (head1 != null) {
            temp.next = head1;
        } else {
            temp.next = head2;
        }
        return dummy.next;
    }
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        int index = 0;
        while (lists.length > 1) {
            int l = lists.length;
            ListNode[] newList = new ListNode[(l + 1) / 2];
            for (int i = 0; i + 1 < l; i += 2) {
                ListNode temp = mergeTwoLists(lists[i], 
                                              lists[i + 1]);
                newList[index++] = temp;
            }
            if (l % 2 == 1) {
                newList[index] = lists[l - 1];
            }
            lists = newList;
            index = 0;
        }
        return lists[0];
    }
}


//merge two by two, iteration, time: O(NlogK), space: O(1)
public class Solution {
    private ListNode mergeTwoLists(ListNode head1, ListNode head2) {
        ListNode dummy = new ListNode(0);
        ListNode temp = dummy;
        while (head1 != null && head2 != null) {
            if (head1.val < head2.val) {
                temp.next = head1;
                head1 = head1.next;
            } else {
                temp.next = head2;
                head2 = head2.next;
            }
            temp = temp.next;
        }
        if (head1 != null) {
            temp.next = head1;
        } else {
            temp.next = head2;
        }
        return dummy.next;
    }
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        int size = lists.length;
        while (size > 1) {
            for (int i = 0, j = size - 1; i < j; i++, j--) {
                lists[i] = mergeTwoLists(lists[i], lists[j]);
            }
            size = (size + 1) / 2;
        }
        return lists[0];
    }
}

No comments:

Post a Comment