23.合并K个升序链表
解题思路:1顺序合并,2分治合并
package leadcode;
import leadcode.lib.ListNode;
import leadcode.lib.ListNodeInit;
import java.util.List;
/**
* @author : icehill
* @description : 合并K个升序链表
* 给你一个链表数组,每个链表都已经按升序排列。
* 请你将所有链表合并到一个升序链表中,返回合并后的链表。
* 示例 1:
* 输入:lists = [[1,4,5],[1,3,4],[2,6]]
* 输出:[1,1,2,3,4,4,5,6]
* 解释:链表数组如下:
* [
* 1->4->5,
* 1->3->4,
* 2->6
* ]
* 将它们合并到一个有序链表中得到。
* 1->1->2->3->4->4->5->6
* 示例 2:
* <p>
* 输入:lists = []
* 输出:[]
* 示例 3:
* <p>
* 输入:lists = [[]]
* 输出:[]
* 提示:
* <p>
* k == lists.length
* 0 <= k <= 10^4
* 0 <= lists[i].length <= 500
* -10^4 <= lists[i][j] <= 10^4
* lists[i] 按 升序 排列
* lists[i].length 的总和不超过 10^4
* <p>
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
* 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
* 解题思路:
* 1.顺序合并链表
* 遍历数组,每次合并两个链表
* 时间复杂度:O(k*n) 空间复杂度:O(1)
* 2.分治合并
* 在1的思想下,先两两合并,每轮合并完变成k/2个链表
* 减少了1中同个元素比较多次的浪费
* 第一轮合并后k个链表合并成了k/2个,平均长度2n/k,
* 然后是k/4个链表,k/8个链表
* 时间复杂度:O(n*logk) 空间复杂度:O(logk)
* @date : 2021-05-01
*/
public class Solution23 {
public static void main(String[] args) {
int[][] array = {{1, 4, 5}, {1, 3, 4}, {2, 6}};
ListNode[] lists = new ListNode[3];
for (int i = 0; i < array.length; i++) {
lists[i] = ListNodeInit.initWhiteArray(array[i]);
}
Solution23 solution23 = new Solution23();
// ListNode head = solution23.mergeKLists(lists);
ListNode head = solution23.mergeKListsPart(lists);
List<Integer> list = ListNodeInit.changeToList(head);
System.out.println(list);
}
/**
* 顺序合并
*
* @param lists
* @return
*/
public ListNode mergeKLists(ListNode[] lists) {
ListNode head = null;
for (int i = 0; i < lists.length; i++) {
head = mergeTwoList(head, lists[i]);
}
return head;
}
/**
* 合并两个有序链表
*
* @param list1
* @param list2
* @return
*/
private ListNode mergeTwoList(ListNode list1, ListNode list2) {
ListNode head = new ListNode(0);
ListNode current = head;
while (list1 != null && list2 != null) {
if (list1.val < list2.val) {
current.next = list1;
list1 = list1.next;
} else {
current.next = list2;
list2 = list2.next;
}
current = current.next;
}
current.next = list1 == null ? list2 : list1;
return head.next;
}
/**
* 分治法(递归)
*
* @param lists
* @return
*/
public ListNode mergeKListsPart(ListNode[] lists) {
return mergePart(lists, 0, lists.length - 1);
}
private ListNode mergePart(ListNode[] lists, int left, int right) {
if (left == right) {
return lists[left];
}
if (left > right) {
return null;
}
//递归每次合并一半数组,类似树形结构,画图就知道了
int mid = (left + right) >> 1;
return mergeTwoList(mergePart(lists, left, mid), mergePart(lists, mid + 1, right));
}
}