题目:
合并k个有序链表,返回合并后的有序链表,并分析实现方法的时空复杂度。
我的想法是依次从待排序的链表中选取一个链表和已经排好序的链表进行合并,当没有待排序的链表时,整个合并过程结束
1 import java.util.*; 2 3 /** 4 * Definition for singly-linked list. 5 * public class ListNode { 6 * int val; 7 * ListNode next; 8 * ListNode(int x) { val = x; } 9 * } 10 */ 11 public class Solution { 12 public ListNode mergeKLists(ListNode[] lists) { 13 ListNode head = new ListNode(0); 14 if(lists != null && lists.length != 0) 15 { 16 for(int i = 0; i < lists.length; i++) //每次从待排序链表lists中选取一个链表和已排好序的head.next链表进行合并 17 { 18 head.next = mergeTwoLists(head.next, lists[i]); 19 } 20 } 21 return head.next; 22 } 23 24 public ListNode mergeTwoLists(ListNode l1, ListNode l2) 25 { 26 if(l1 == null || l2 == null) 27 { 28 return l1 == null ? l2 : l1; 29 } 30 ListNode head = l1.val <= l2.val ? l1 : l2; 31 ListNode cur1 = head == l1 ? l1 : l2; 32 ListNode cur2 = head == l1 ? l2 : l1; 33 ListNode pre = null; 34 ListNode next = null; 35 while(cur1 != null && cur2 != null) 36 { 37 if(cur1.val <= cur2.val) 38 { 39 pre = cur1; 40 cur1 = cur1.next; 41 } 42 else 43 { 44 next = cur2.next; 45 pre.next = cur2; 46 cur2.next = cur1; 47 pre = cur2; 48 cur2 = next; 49 } 50 } 51 pre.next = cur1 == null ? cur2 : cur1; 52 return head; 53 } 54 }
// 该方法的时间复杂度为O(k*N),其中k代表,lists中的元素个数,N代表所有的待排序节点的个数
// 空间复杂度为O(1)
官方题解给出了一种分治方法,可以减少节点比较的次数,将时间复杂度降低为O(Nlogk),点击查看 https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/he-bing-kge-pai-xu-lian-biao-by-leetcode/
1 import java.util.*; 2 3 /** 4 * Definition for singly-linked list. 5 * public class ListNode { 6 * int val; 7 * ListNode next; 8 * ListNode(int x) { val = x; } 9 * } 10 */ 11 public class Solution { 12 public ListNode mergeKLists(ListNode[] lists) { 13 if(lists == null || lists.length == 0) 14 { 15 return null; 16 } 17 18 int len = lists.length; 19 int interval = 1; 20 while(interval < len) 21 { 22 for(int i = 0; i < len - interval; i += 2*interval) 23 { 24 lists[i] = mergeTwoLists(lists[i], lists[i+interval]); // 归并的思想,两两合并 25 } 26 interval *= 2; 27 } 28 return lists[0]; 29 30 } 31 32 public ListNode mergeTwoLists(ListNode l1, ListNode l2) 33 { 34 if(l1 == null || l2 == null) 35 { 36 return l1 == null ? l2 : l1; 37 } 38 ListNode head = l1.val <= l2.val ? l1 : l2; 39 ListNode cur1 = head == l1 ? l1 : l2; 40 ListNode cur2 = head == l1 ? l2 : l1; 41 ListNode pre = null; 42 ListNode next = null; 43 while(cur1 != null && cur2 != null) 44 { 45 if(cur1.val <= cur2.val) 46 { 47 pre = cur1; 48 cur1 = cur1.next; 49 } 50 else 51 { 52 next = cur2.next; 53 pre.next = cur2; 54 cur2.next = cur1; 55 pre = cur2; 56 cur2 = next; 57 } 58 } 59 pre.next = cur1 == null ? cur2 : cur1; 60 return head; 61 } 62 }
// 关于归并,还有一种比较好的实现,来自https://leetcode-cn.com/problems/merge-k-sorted-lists/solution/leetcode-23-he-bing-kge-pai-xu-lian-biao-by-powcai/
1 public ListNode mergeKLists(ListNode[] lists) { 2 if(lists == null || lists.length == 0) 3 { 4 return null; 5 } 6 return merge(lists, 0, lists.length - 1); 7 } 8 9 public ListNode merge(ListNode[] lists, int left, int right) 10 { 11 if(left == right) return lists[left]; 12 int mid = (left + right) / 2; 13 ListNode l1 = merge(lists, left, mid); 14 ListNode l2 = merge(lists, mid+1, right); 15 return mergeTwoLists(l1, l2); 16 }