题目:
合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。
数据范围:节点总数满足 0≤n≤10^5,链表个数满足 1≤k≤10^5 ,每个链表的长度满足 1≤len≤200,每个节点的值满足 ∣val∣<=1000。
要求:时间复杂度 O(nlogk)。
示例1
输入:[{1,2,3},{4,5,6,7}]
返回值:{1,2,3,4,5,6,7}
示例2
输入:[{1,2},{1,4,5},{6}]
返回值:{1,1,2,4,5,6}
思路:
分治法。先将链表集合拆分为单个链表,然后再用上一题的合并两个排序链表的方法,将链表两两依次合并,最终返回合并后的链表。
代码:
import java.util.*;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
//分治法
public ListNode mergeKLists(ArrayList<ListNode> lists) {
return devideMerge(lists, 0, lists.size() - 1);
}
ListNode devideMerge(ArrayList<ListNode> lists, int left, int right) {
//1.边界条件判断
if(left > right) {
return null;
}else if(left == right) {
//其实就是分治的分的退出条件,就是left == right
return lists.get(left);
}
//2.分
//有可能(left + right) > Integer的上限
//此处优化可以写为left + (right - left) / 2
int mid = (left + right) / 2;
//3.合
return merge(devideMerge(lists, left, mid), devideMerge(lists, mid + 1, right));
}
public ListNode merge(ListNode list1,ListNode list2) {
ListNode dummy = new ListNode(-1);
ListNode res = dummy;
while(list1 != null && list2 != null) {
if(list1.val < list2.val) {
res.next = list1;
list1 = list1.next;
res = res.next;
} else {
res.next = list2;
list2 = list2.next;
res = res.next;
}
}
if(list1 != null) {
res.next = list1;
}
if(list2 != null) {
res.next = list2;
}
return dummy.next;
}
}