[leetcode] Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
https://oj.leetcode.com/problems/merge-k-sorted-lists/
思路1(naive):1跟2合并,然后跟3合并,然后跟4合并,一直到k个合并完。
复杂度:1,2合并访问2n个节点,12与3合并访问3n个节点,...,123~k-1与k合并访问kn个节点,总共遍历节点数目n(3+4+5+...+k),O(nk^2)。
思路2:mergeSort的思想,K个链表先划分为合并两个k/2的链表,每个k/2的链表在划分为k/4的链表,一直到只剩一个或者两个链表。
复杂度:T(k)=2T(k/2)+O(nk),根据 主定理(算法导论上有讲),复杂度为O(nklogk)。
思路3:维护一个大小为k的堆。每次取堆顶元素放到结果中,并把该元素的后继(如果有)放入堆中。
复杂度:每个元素读取一次nk,堆操作logk,所以复杂度为O(nklogk)。
思路2代码:
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; }
思路3代码(加测试代码):
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; } }
第二遍记录:
归并法:注意cornor case,lists==null or lists.size()==0.
public class Solution { public ListNode mergeKLists(List<ListNode> lists) { if(lists==null||lists.size()==0) return null; return merge(lists,0,lists.size()-1); } private ListNode merge(List<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 dummyHead = new ListNode(-1); ListNode p =dummyHead; while(l1!=null&&l2!=null){ if(l1.val<=l2.val){ p.next =l1; l1=l1.next; } else{ p.next=l2; l2=l2.next; } p=p.next; } if(l1!=null) p.next=l1; if(l2!=null) p.next=l2; return dummyHead.next; } }
用PriorityQueue的方法,注意自定义Comparator。
public class Solution { public ListNode mergeKLists(List<ListNode> lists) { if(lists==null) return null; PriorityQueue<ListNode> pq = new PriorityQueue<ListNode>(20, new Comparator<ListNode>(){ @Override public int compare(ListNode a, ListNode b){ return a.val-b.val; } }); ListNode dummyHead = new ListNode(-1); for(int i=0;i<lists.size();i++){ ListNode head = lists.get(i); if(head!=null) pq.add(head); } ListNode cur = dummyHead; while(!pq.isEmpty()){ ListNode out = pq.remove(); cur.next = out; cur = cur.next; if(out.next!=null) pq.add(out.next); } return dummyHead.next; } }
参考:
http://blog.csdn.net/linhuanmars/article/details/19899259
http://www.cnblogs.com/TenosDoIt/p/3673188.html