问题来源:选自leetCode 23:合并K个排序链表
问题描述:
题目给定信息:
不确定需要合并的链表的数目,但依然要求我们把给定的这些有序链表合并成一个链表,并且保证合并的链表依然是有序的。
问题分析:
我们可以使用暴力合并的方法,就是不管有多少个链表,先让第一个链表和第二个链表进行合并,合并之后的结果在和第三个链表进行合并,依次进行下去直到把全部的链表全部合并成一个链表,这种方法是最简单最易想到的方法,但是时间复杂度太高了;还有一种方法是把所有链表中的节点值保存到一个数组中,然后对这个数组进行从小到大的排序,排序完成后再通过循环为每个节点值new成一个节点对象,最后再把节点节点串联起来,这样做相比暴力求解时间复杂度要低一些,但是依然不是最优的求解方法;最优的求解方法就是使用分治思想。
函数实现:
方法一(使用数组排序的方法求解多个有序链表的合并问题):
1 LinkedList<Integer> list = new LinkedList<>(); 2 // 循环遍历lists数组,把该数组中每一个链表中的每一个元素全部都存入list集合中 3 for (int i = 0; i < lists.length; i++) { 4 ListNode temp_Head = lists[i]; 5 while (temp_Head != null) { 6 list.add(temp_Head.val); 7 temp_Head = temp_Head.next; 8 } 9 } 10 //判断lists是否为空,如果为空则返回null,不在这里进行验证的话,Leetcode的边界检测不通过 11 if(list.size()==0){ 12 return null; 13 } 14 //将list转换为数组方便使用Arrays.sort()函数进行排序 15 Integer[] array_val = list.toArray(new Integer[0]); 16 Arrays.sort(array_val); 17 ListNode[] array = new ListNode[array_val.length]; 18 //将排序后的数组全部在生成对应的ListNode对象。此时的对象就已经是有序的 19 for (int i = 0; i < array_val.length; i++) { 20 array[i] = new ListNode(array_val[i]); 21 } 22 // 把ListNode[] array数组连接成一个链表 23 for (int i = 0; i < array.length - 1; i++) { 24 array[i].next = array[i + 1]; 25 } 26 return array[0]; 27 }
方法二(分治思想):
1 public ListNode mergeKLists(ListNode[] lists) { 2 if (lists.length == 0) { 3 return null; 4 } 5 if (lists.length == 1) { 6 return lists[0]; 7 } 8 if (lists.length == 2) { 9 return mergeTwoLists(lists[0], lists[1]); 10 } 11 int mid = lists.length / 2; 12 ListNode[] lists_sub1 = new ListNode[mid]; 13 ListNode[] lists_sub2 = new ListNode[lists.length - mid + 1]; 14 for(int i=0;i<mid;i++){ 15 lists_sub1[i]=lists[i]; 16 } 17 for(int i=mid;i<lists.length;i++){ 18 lists_sub2[i]=lists[i]; 19 } 20 ListNode l1=mergeKLists(lists_sub1); 21 ListNode l2=mergeKLists(lists_sub2); 22 return mergeTwoLists(l1,l2); 23 } 24 25 public ListNode mergeTwoLists(ListNode l1, ListNode l2) { 26 ListNode newHead = new ListNode(0); 27 ListNode temp_newHead = newHead; 28 while (l1 != null && l2 != null) { 29 if (l1.val < l2.val) { 30 temp_newHead.next = l1; 31 l1 = l1.next; 32 } else { 33 temp_newHead.next = l2; 34 l2 = l2.next; 35 } 36 temp_newHead = temp_newHead.next; 37 } 38 if (l1 != null) { 39 temp_newHead.next = l1; 40 } 41 if (l2 != null) { 42 temp_newHead.next = l2; 43 } 44 return newHead.next; 45 }
运行结果:
方法一的运行结果:
方法二的运行结果: