23. Merge k Sorted Lists
Brute Force
所有node sort一遍
time complexity - O(NlogN) [N = the total number of nodes in all linked lists]
space complexity - O(N)
Divide and Conquer | MergeSort
Use merge two,两两合并最后成一个
不同方法写merge2, check out: LeetCode - 21. Merge Two Sorted Lists_real_lisa的博客-CSDN博客
def mergeTwoLists(self, list1: ListNode, list2: ListNode) -> ListNode:
res = head = ListNode(0);
while(list1 and list2):
if list1.val < list2.val:
res.next = list1
list1 = list1.next
else:
res.next = list2
list2 = list2.next
res = res.next
res.next = list1 or list2
return head.next
Most optimized for merge two:
time complexity - O(2n) [n = average num of nodes in each Linked List]
space complexity - O(1) in-place
Recursion
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if not lists: return None
length = len(lists)
if length == 1: return lists[0]
mid = int(length/2)
return self.mergeTwoLists(self.mergeKLists(lists[:mid]), self.mergeKLists(lists[mid:]))
Iteration 1
class Solution(object):
def mergeKLists(self, lists):
"""
:type lists: List[ListNode]
:rtype: ListNode
"""
amount = len(lists)
interval = 1
while interval < amount:
for i in range(0, amount - interval, interval * 2):
lists[i] = self.merge2Lists(lists[i], lists[i + interval])
interval *= 2
return lists[0] if amount > 0 else lists
Iteration 2
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
if not lists: return None
length = len(lists)
while(length != 1):
newLists = []
if len(lists)%2 == 1: newLists.append(lists[-1])
for i in range(1, length, 2):
newLists.append(self.mergeTwoLists(lists[i-1], lists[i]))
lists = newLists
length = len(lists)
return lists[0]
Iteration 3
class Solution {
public:
ListNode *mergeKLists(vector &lists) {
if(lists.empty()) return NULL;
int end = lists.size()-1;
while(end>0) {
int begin = 0;
while(begin
Time Complexity
k = num of Linked List
n = average num of nodes in each Linked List
2n*k/2 + 4n*k/4 + ... + (2^x)*n*k/(2^x)
= n*k + n*k + ... + n*k (有x个这样的n*k)
= n*k*x
explain 2n*k/2:
第一次运行:每两个Linked List的num of nodes=2n, 运行merge2合并为O(2n);有k/2对这样的Linked List,所以第一次两两合并的time complexity是2n*k/2
(2^x)*n*k/(2^x)为最后一次运行,k/(2^x)为最后剩余Linked List的个数,所以k/(2^x)=1, 得x=logk
n*k*x = n*k*(logk)
所以最后的time complexity为
O(nklogk) = O(Nlogk) [N = nk = the total number of nodes in all linked lists]
Heap
每次选择k lists中最小的
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
heap = [(node.val, i, node) for i,node in enumerate(lists) if node]
heapq.heapify(heap)
cur = dummy = ListNode(0)
while heap:
val, i, node = heapq.heappop(heap)
cur.next = ListNode(val)
cur = cur.next
if node.next:
heapq.heappush(heap, (node.next.val, i, node.next))
return dummy.next
Time Complexity
k = num of Linked List
N = the total number of nodes in all linked lists
每次选择k lists中最小的 - O(logk),选择N次 ----> O(Nlogk)