题目链接: https://oj.leetcode.com/problems/merge-k-sorted-lists/
问题:
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
解题思路:
方法一:暴力破解
思路:
将列表一个一个地合并(例如:lists = [l1, l2, l3, l4],首先合并l1和l2,然后将合并后的结果与l3合并,…)
复杂度分析:
时间:
假设有k个列表,每个列表的长度为n,需要k-1次合并操作,第1次操作将2个长度为n的列表合并,最多需要n+n次比较,第二次操作将一个长度为2n和一个长度为n的列表合并,最多需要2n+n次比较,后一次合并需要的最多比较次数比前一次合并多n,所以总的比较次数为 2n + 3n +4n + … + kn = n(k(k+1)/2 - 1) = O(nk^2)
方法二:运用小顶堆
思路:
小顶堆的大小为k
1)首先用每个列表的最小元素初始化堆;
2)从堆中返回最小元素之后将它所在的列表中下一个元素插入堆中;
3)重复2)中操作,直到所有列表为空
复杂度分析:
时间:
总共有nk个元素,将每个元素插入堆的操作时间复杂度为O(logk)。
所以,总时间复杂度为O(nklogk)
空间:
额外分配的堆空间为O(k)
1 private static final Comparator<ListNode> listComparator = new Comparator<ListNode>(){ 2 @Override 3 public int compare(ListNode x, ListNode y) { 4 return x.val - y.val; 5 } 6 }; 7 8 public ListNode mergeKLists(ListNode[] lists) { 9 if(lists.length == 0){ 10 return null; 11 } 12 Queue<ListNode> queue = new PriorityQueue<>(lists.length, listComparator); 13 14 for(ListNode node: lists){ 15 if(node != null){ 16 queue.add(node); 17 } 18 } 19 20 ListNode dummyHead = new ListNode(0); 21 ListNode p = dummyHead; 22 while (!queue.isEmpty()){ 23 ListNode node = queue.poll(); 24 p.next = node; 25 p = p.next; 26 if(node.next != null){ 27 queue.add(node.next); 28 } 29 } 30 return dummyHead.next; 31 }
方法三:分而治之
思路:
采用两两合并的方法
列表数目变化为:k -> k/2 -> k/4 -> … -> 2 -> 1
同时,列表长度变化为: n -> 2n -> 4n -> … -> n * 2^logk
复杂度分析:
时间:
k * n + (k / 2) *2n + … + n * 2^logk * 1
= nk + nk + …+ nk
= nklogk
总时间复杂度为O(nklogk)
空间:
O(1)
1 public ListNode mergeKLists(ListNode[] lists) { 2 if(lists.length == 0){ 3 return null; 4 } 5 int end = lists.length - 1; 6 while(end > 0){ 7 int begin = 0; 8 while(begin < end){ 9 lists[begin] = merge2Lists(lists[begin], lists[end]); 10 begin++; 11 end--; 12 } 13 } 14 return lists[0]; 15 } 16 17 private ListNode merge2Lists(ListNode l1, ListNode l2){ 18 ListNode dummyHead = new ListNode(0); 19 ListNode p = dummyHead; 20 while(l1 != null && l2 != null){ 21 if(l1.val < l2.val){ 22 p.next = l1; 23 l1 = l1.next; 24 }else{ 25 p.next = l2; 26 l2 = l2.next; 27 } 28 p = p.next; 29 } 30 if(l1 != null){ 31 p.next = l1; 32 } 33 if(l2 != null){ 34 p.next = l2; 35 } 36 return dummyHead.next; 37 } 38