合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6
1 //方法一:使用优先级队列实现 2 public class MergekSortedLists { 3 private class ListNode { 4 int val; 5 ListNode next; 6 ListNode(int x) { 7 val = x; 8 } 9 } 10 //时间复杂度:O(n*log(k)),n为元素总个数,每一个都要遍历输出,k为链表个数,队列中元素个数为链表数(k个元素),需要对其进行小根堆调整 11 public ListNode mergeKLists(ListNode[] lists) { 12 if(lists == null) { 13 throw new IllegalArgumentException("输入参数错误"); 14 } 15 PriorityQueue<ListNode> pq = new PriorityQueue<>(10, new Comparator<ListNode>() { 16 @Override 17 public int compare(ListNode l1, ListNode l2) { 18 //构建小根堆(由PriorityQueue源码决定) 19 if(l1.val > l2.val) { 20 return 1; 21 }else if(l1.val == l2.val) { 22 return 0; 23 }else { 24 return -1; 25 } 26 } 27 }); 28 ListNode result = new ListNode(0); 29 ListNode cur = result; 30 for(ListNode node : lists) { 31 if(node != null) { 32 pq.add(node); 33 } 34 } 35 36 //遍历n次,每次小根堆调整log(k)次 37 while(!pq.isEmpty()) { 38 cur.next = pq.poll(); 39 cur = cur.next; 40 if(cur.next != null) { 41 pq.add(cur.next); 42 } 43 } 44 return result.next; 45 } 46 47 //方法三:使用分治法实现 48 public ListNode mergKLists2(ListNode[] lists) { 49 if(lists == null || lists.length == 0) { 50 throw new IllegalArgumentException("输入参数错误"); 51 } 52 return merge(lists, 0, lists.length-1); 53 } 54 public ListNode merge(ListNode[] lists, int left, int right) { 55 if(left >= right) { //此处可以为left == right 56 return lists[left]; 57 } 58 int mid = left + (right - left) / 2; //left >= mid, 因为left<right, 所以right >= mid+1 59 ListNode l1 = merge(lists, left, mid); //将链表集合一直分为单个,两两进行比较 60 ListNode l2 = merge(lists, mid+1, right); 61 return mergeTwoListNode(l1, l2); 62 } 63 public ListNode mergeTwoListNode(ListNode l1, ListNode l2) { 64 //将两个链表进行合并,返回的是合并后的有序链表 65 if(l1 == null) { 66 return l2; 67 }else if(l2 == null) { 68 return l1; 69 } 70 if(l1.val < l2.val) { //若l1值小,则返回l1节点, 71 l1.next = mergeTwoListNode(l1.next, l2); 72 return l1; 73 }else { 74 l2.next = mergeTwoListNode(l1, l2.next); 75 return l2; 76 } 77 } 78 }