题目
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
解题
该题的重点就是将原问题的k个链表合并分解为子问题:2个排序链表的合并Leetcode | 21. 合并两个有序链表 ,这样问题就简单很多,只用考虑两个排序链表怎么合并,这个合并方式和归并排序的合并实质其实是一样的,具体可以看 这篇博文 里对归并排序的合并方式介绍。
两个链表合并的逻辑如下:
链表1:list1,指针p;链表2:list2,指针为q,分别从链表的第一个开始
p与q比较,较小的min(p,q)加入结果reslist中,较小的那一个指针向后移动选择next元素继续比较大小,重复上述步骤。
顺序依次合并
已知输入k个排序链表,从前两个开始,合并为一个链表后再和下一个链表进行合并,一直到最后一个链表,这样就把问题分解为每次都解决的是2个链表的合并问题。
以4个排序链表合并为例,合并方式如下图:
合并2链表递归实现
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
//把问题分解为 两个合并链表的情况 和归并排序的合并一样
ListNode res = null;
for(ListNode list:lists){
res = merge2Lists(res,list);//将合并的结果与下一个链表进行合并,初始第一个链表可以当作是初始空结果与第一个链表的合并结果
}
return res;
}
//合并两个链表 递归方法
public ListNode merge2Lists(ListNode l1, ListNode l2){
if(l1 == null) return l2;
if(l2 == null) return l1;
//从两个链表的第一个数开始比较
if(l1.val < l2.val){
l1.next = merge2Lists(l1.next,l2);//l1第一个数比较小的话,把l1放在第一个,后面放的时候递归剩下的数的合并结果
return l1;
}else{
l2.next = merge2Lists(l1,l2.next);
return l2;
}
}
}
合并2链表迭代实现
class Solution {
public ListNode mergeKLists(