BM5. [合并k个已排序的链表]

https://www.nowcoder.com/exam/oj?tab=%E7%AE%97%E6%B3%95%E7%AF%87&topicId=295
BM5. 合并k个已排序的链表
题目分析
上一道题目你已经掌握地非常清楚了,在复用合并两个有序链表函数的基础上,给这个题目引入一个归并算法就能轻松解决这道题目。所以这道题目值得多刷几遍,感受一下归并分治的思想
做法分析
复用合并两个排序链表函数
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//先判断两者是否为空的情况
if(l1 == null)
return l2;
if(l2 == null)
return l1;
ListNode mergeNode = null;
// 两个需要合并的队列都不为空的情况那需要确定头结点
if(l1.val < l2.val){
mergeNode = l1;
mergeNode.next = mergeTwoLists(l1.next, l2);
}else{
mergeNode = l2;
mergeNode.next = mergeTwoLists(l1, l2.next);
}
return mergeNode;
}
写分解K个链表的函数,确定区间left,right,确定何时(left==right)返回归并的对象。归并函数写起来非常的简单
public ListNode mergeInternal(ArrayList<ListNode> lists, int left, int right){
//如果区间已经闭合,返回最小的区间值
if(left == right){
return lists.get(left);
}
if(left > right){
return null;
}
int mid = left + (right - left) / 2;
// 合并两个小区间
return mergeTwoLists(mergeInternal(lists, left, mid), mergeInternal(lists, mid + 1, right));
}
连接主干函数,这种相对比较复杂的题目不要害怕写得函数比较多,只要确保每个函数职责明确就没有问题
public ListNode mergeKLists(ArrayList<ListNode> lists) {
int left = 0;
int right = lists.size() - 1;
return mergeInternal(lists, left, right);
}
完整题解
public ListNode mergeKLists(ArrayList<ListNode> lists) {
int left = 0;
int right = lists.size() - 1;
return mergeInternal(lists, left, right);
}
public ListNode mergeInternal(ArrayList<ListNode> lists, int left, int right){
if(left == right){
return lists.get(left);
}
if(left > right){
return null;
}
int mid = left + (right - left) / 2;
return mergeTwoLists(mergeInternal(lists, left, mid), mergeInternal(lists, mid + 1, right));
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//先判断两者是否为空的情况
if(l1 == null)
return l2;
if(l2 == null)
return l1;
ListNode mergeNode = null;
// 两个需要合并的队列都不为空的情况那需要确定头结点
if(l1.val < l2.val){
mergeNode = l1;
mergeNode.next = mergeTwoLists(l1.next, l2);
}else{
mergeNode = l2;
mergeNode.next = mergeTwoLists(l1, l2.next);
}
return mergeNode;
}
复杂度分析
时间复杂度:,归并排序的时间复杂度
空间复杂度:需要额外开辟空间返回链表

