MergeKSorted linked lists and return it as one sorted list. analyze and describe its complexity.
Https://oj.leetcode.com/problems/merge-k-sorted-lists/
Idea 1 (naive): Merge 1 and 2, then merge 3, and then merge 4 until K are merged.
Complexity: 1 and 2 merge and access 2n nodes, 12 and 3 merge and access 3N nodes,..., 123 ~ The K-1 and K merge to access kN nodes, total traverse node number N (3 + 4 + 5 +... + k), O (NK ^ 2 ).
Idea 2: mergesort: K linked lists are first divided into two K/2 linked lists. Each K/2 linked list is divided into k/4 linked lists, only one or two linked lists are left.
Complexity: T (K) = 2 T (K/2) + O (NK). According to the main theorem (introduced in the introduction to algorithms), the complexity is O (nklogk ).
Idea 3: maintain a heap with a size of K. Place the top element of the heap into the result, and add the successor (if any) of the element to the heap.
Complexity: Each element reads NK once and heap logk, so the complexity is O (nklogk ).
Idea 2 code:
public ListNode mergeKLists(ArrayList<ListNode> lists) { if (lists == null) return null; return merge(lists, 0, lists.size() - 1); } private ListNode merge(ArrayList<ListNode> lists, int start, int end) { if (start == end) return lists.get(start); int mid = (start + end) / 2; ListNode one = merge(lists, start, mid); ListNode two = merge(lists, mid + 1, end); return mergeTwoLists(one, two); } private ListNode mergeTwoLists(ListNode l1, ListNode l2) { if (l1 == null) return l2; if (l2 == null) return l1; ListNode p1 = l1; ListNode p2 = l2; ListNode head = new ListNode(-1); head.next = p1.val <= p2.val ? p1 : p2; ListNode tail = head; while (p1 != null && p2 != null) { if (p1.val <= p2.val) { tail.next = p1; ListNode oldP1 = p1; p1 = p1.next; oldP1.next = null; tail = oldP1; } else { tail.next = p2; ListNode oldP2 = p2; p2 = p2.next; oldP2.next = null; tail = oldP2; } } if (p1 != null) tail.next = p1; if (p2 != null) tail.next = p2; return head.next; }
Train of Thought 3 code (add test code ):
import java.util.ArrayList;import java.util.Comparator;import java.util.PriorityQueue;import java.util.Random;public class Solution { public ListNode mergeKLists(ArrayList<ListNode> lists) { if (lists == null) return null; PriorityQueue<ListNode> pq = new PriorityQueue<ListNode>(20, new Comparator<ListNode>() { @Override public int compare(ListNode o1, ListNode o2) { return o1.val - o2.val; } }); ListNode head = new ListNode(-1); ListNode cur = head; for (int i = 0; i < lists.size(); i++) { if (lists.get(i) != null) pq.add(lists.get(i)); } while (!pq.isEmpty()) { ListNode out = pq.remove(); cur.next = out; cur = cur.next; if (out.next != null) pq.add(out.next); } return head.next; } public static void main(String[] args) { ArrayList<ListNode> lists = new ArrayList<ListNode>(); int k = 3; for (int i = 0; i < k; i++) { ListNode list = makeList(getRandomArray()); lists.add(list); printList(list); } printList(new Solution().mergeKLists(lists)); } private static int[] getRandomArray() { Random rand = new Random(); int size = rand.nextInt(10); int[] res = new int[size]; if (size == 0) return res; res[size - 1] = 100; for (int i = size - 2; i >= 0; i--) { res[i] = rand.nextInt(res[i + 1] + 1); } return res; } private static ListNode makeList(int[] a) { ListNode head = new ListNode(-1); ListNode p = head; for (int i = 0; i < a.length; i++) { p.next = new ListNode(a[i]); p = p.next; } return head.next; } private static void printList(ListNode head) { while (head != null) { System.out.print(head.val); if (head.next != null) System.out.print("->"); head = head.next; } System.out.println(); }}class ListNode { int val; ListNode next; ListNode(int x) { val = x; next = null; }}
Refer:
Http://blog.csdn.net/linhuanmars/article/details/19899259
Http://www.cnblogs.com/TenosDoIt/p/3673188.html