题目
Merge
k
sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
思路
将数组中的k个有序链表归并成一个有序链表,并分析时间复杂度。该题可以在第22题-"merge two sorted lists"的基础上设计算法。
一开始想到遍历数组的k-1个链表,将第一个链表与第二个链表合并成一个新链表,然后第三个链表再跟这个新链表合并成新链表,以此类推......假设链表长度最长为n,则这样设计出来的算法时间复杂度为O(n*k),提交报超时错误。
改变思路,不要用单一遍历方式。可以递归归并数组中的k个链表,将其分割成k/2大小的数组归并,然后再分成k/2^2大小的数组归并......这样递归归并的时间复杂度为O(logk),总时间复杂度为O(n*logk)
代码
Python
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
if(len(lists) == 0):
return
return self.merge(lists,0,len(lists) - 1)
def merge(self,lists,start,end):
if(start == end):
return lists[start]
if(end - start == 1):
return self.mergeTwoLists(lists[start],lists[end])
mid = start + (end - start)/2
return self.mergeTwoLists(self.merge(lists,start,mid),self.merge(lists,mid+1,end))
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
head = ListNode(0)
cur = head
while(l1 != None and l2 != None):
#遍历l1和l2的节点并比较大小,将小的放入目标链表中,cur为游标
if(l1.val < l2.val):
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur.next.next = None
cur = cur.next
#比较完l1和l2后还有剩余节点
if(l1 != None):
cur.next = l1
else:
cur.next = l2
return head.next
Java
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
public class Solution {
public ListNode mergeKLists(ListNode[] lists) {
if (lists.length == 0)
return null;
return merge(lists, 0, lists.length - 1);//另外定义了一个根据数组下标merge的函数
}
public ListNode merge(ListNode[] lists, int start, int end) {
if (start == end)
return lists[start];
if (end - start == 1)
return mergeTwoLists(lists[start], lists[end]);
int mid = start + (end - start) / 2;
//递归merge,merge k/2个,k/2^2,k/2^3...直到merge两个或一个
return mergeTwoLists(merge(lists, start, mid),merge(lists, mid + 1, end));
}
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode head = new ListNode(0);
ListNode cur = head;
// 遍历l1和l2的节点并比较大小,cur代表当前节点
while (l1 != null && l2 != null) {
if (l1.val < l2.val) {
cur.next = l1;
l1 = l1.next;
} else {
cur.next = l2;
l2 = l2.next;
}
cur.next.next = null;// 可减少链表大小,提高效率
cur = cur.next;
}
// 比较完l1和l2的节点后还有剩余节点
if (l1 != null)
cur.next = l1;
else
cur.next = l2;
return head.next;
}
}