一、题目描述
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入: [ 1->4->5, 1->3->4, 2->6 ] 输出: 1->1->2->3->4->4->5->6
二、解题思路
(1)用循环做
思路: 已经解决了两个排序链表的问题,则k个链表的排序也进行依次遍历即可解决;因为两个链表合并的时间复杂度是O(n),空间复杂度是O(1);k个链表是外加一次循环,所以时间复杂度为O(n*m)(n为lists数组的长度,m为数组中链表的长度),空间复杂度为O(1)
(2)用二分法,递归做
类似于归并排序的二分思想来做。
三、可运行java代码
(1)方法一:循环做
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
//思路: 已经解决了两个排序链表的问题,则k个链表的排序也进行依次遍历即可解决
//因为两个链表合并的时间复杂度是O(n),空间复杂度是O(1);k个链表是外加一次循环,所以时间复杂度为O(n*m)(n为lists数组的长度,m为数组中链表的长度),空间复杂度为O(1)
ListNode result = null;
for(ListNode list:lists){
result = mergeTwoList(result,list);
}
return result;
}
public static ListNode mergeTwoList(ListNode l1,ListNode l2){
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
ListNode head = new ListNode(0);
ListNode temp = head;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
temp.next = l1;
temp = temp.next;
l1 = l1.next;
}else{
temp.next = l2;
temp = temp.next;
l2 = l2.next;
}
}
if(l1 == null){
temp.next = l2;
}
if(l2 == null){
temp.next = l1;
}
return head.next;
}
}
(2)方法二:用递归做(二分)
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if(lists == null || lists.length == 0){
return null;
}
return mergeList(lists, 0, lists.length - 1);
}
public ListNode mergeList(ListNode[] lists, int left, int right){
if(left >= right)
return lists[left];
int mid = left + (right - left) / 2;
ListNode l1 = mergeList(lists, left, mid);
ListNode l2 = mergeList(lists, mid + 1, right);
return merge(l1, l2);
}
public ListNode merge(ListNode l1, ListNode l2){
if(l1 == null) return l2;
if(l2 == null) return l1;
ListNode ans = new ListNode(0);
ListNode p = ans;
while(l1 != null && l2 != null){
if(l1.val <= l2.val){
p.next = l1;
l1 = l1.next;
}
else{
p.next = l2;
l2 = l2.next;
}
p = p.next;
}
p.next = l1 == null? l2 : l1;
return ans.next;
}
}