合併 k 個排序鍊錶,返回合併後的排序鍊錶。請分析和描述演算法的複雜度。
採用分治法的思想,將 k 個排序鍊錶先合併為 k/2 個鍊錶。依次迴圈,直至合併為1個鍊錶為止。
注意:從 k 到 k/2 時,如何定義索引,將每兩個鍊錶合併,而且必須符合奇數、偶數個鍊錶的情況。
解決辦法:
k = (n+1)/2; lists[i] = self.merge2lists(lists[i], lists[i+k])
# definition for singly-linked list.
# class listnode(object):
# def __init__(self, x):
# self.val = x
# self.next = none
class
solution
(object):
defmergeklists
(self, lists)
:"""
:type lists: list[listnode]
:rtype: listnode
"""if lists ==
:return
n =len(lists)
while n>1:
# 採用分治法,將所有列表兩兩合併,將複雜度減半
k =(n+1)/
2for i in
range
(n/2):
lists[i]
= self.merge2lists(lists[i]
, lists[i+k]
) n = k
return lists[0]
defmerge2lists
(self, l1, l2)
: head = listnode(-1
) temp = head
# 如果兩個鍊錶都非空
while l1 and l2:
if l1.val < l2.val:
temp.
next
= l1
l1 = l1.
next
else
: temp.
next
= l2
l2 = l2.
next
temp = temp.
next
if l1:
temp.
next
= l1
if l2:
temp.
next
= l2
return head.
next
將每個鍊錶中的首元素取出來,構建乙個最小堆(加入最小堆中);
取出堆頂元素(自動更新為整個堆中最小的元素),把取出元素的下乙個元素加入堆中;
對堆重新排序;(只需要對根節點即索引為 0 的位置進行最小堆化)
迴圈上述操作,直至堆中沒有元素,此時 k 個鍊錶也合併為乙個鍊錶,返回首節點即可。
問題:如何將取出元素的下乙個元素加入堆中,記錄索引?
將取出的元素以鍊錶節點的形式加入堆中,按照 .val屬性排序,按照 .next屬性讀取下乙個元素。
彈出堆頂元素
堆頂元素在索引為 0的位置。heap.pop(0)
超出時間限制
將堆頂元素彈出之後,只需要對堆頂元素重新進行堆最小化的操作。min_heapify(heap, 0)
# definition for singly-linked list.
# class listnode(object):
# def __init__(self, x):
# self.val = x
# self.next = none
class
solution
(object):
defmergeklists
(self, lists)
:"""
:type lists: list[listnode]
:rtype: listnode
"""if lists ==
:return
n =len(lists)
if n<=1:
return lists[0]
min_heap =
for list1 in lists:
if list1:
head = listnode(-1
) temp = head
self.build_min_heap(min_heap)
while min_heap:
# 彈出最小元素,在索引為 0 的位置
temp.
next
= min_heap[0]
temp = temp.
next
if temp.
next
: min_heap[0]
= temp.
next
else
: min_heap[0]
= min_heap[-1
] min_heap.pop(
)# 只需要對索引0進行堆最小化操作
self.min_heapify(min_heap,0)
return head.
next
defmin_heapify
(self, heap,i)
: n =
len(heap)
# 左兒子
left =
2* i+
1# 右兒子
right =
2* i +
2# 取出三者中的最大值對應的索引
if left < n and heap[left]
.val < heap[i]
.val:
smallest = left
else
: smallest = i
if right < n and heap[right]
.val < heap[smallest]
.val:
smallest = right
if smallest != i:
heap[i]
, heap[smallest]
= heap[smallest]
, heap[i]
self.min_heapify(heap,smallest)
defbuild_min_heap
(self, nums)
: size =
len(nums)
# 輸入異常情況
if nums is
none
or size<=0:
return
if size ==1:
return nums
for i in
range
(size //2,
-1,-
1): self.min_heapify(nums, i)
23 合併K個排序鍊錶
合併 k 個排序鍊錶,返回合併後的排序鍊錶。請分析和描述演算法的複雜度。示例 輸入 1 4 5,1 3 4,2 6 輸出 1 1 2 3 4 4 5 6 偷懶直接複製了以前的堆的 所有看上去長了點 class priorityqueue priority是設定優先順序 true為大根堆 false為...
23 合併K個排序鍊錶
合併 k 個排序鍊錶,返回合併後的排序鍊錶。請分析和描述演算法的複雜度。示例 輸入 1 4 5,1 3 4,2 6 輸出 1 1 2 3 4 4 5 6 暴力法 將所有的節點放在乙個陣列中,然後對陣列排序,最後遍歷陣列,組建新的鍊錶。definition for singly linked list...
23 合併K個排序鍊錶
題目.很有意思 第一想法就是使用最小堆或者比較樹,這個方法當然是可以的,但是用go語言難寫,尤其是比較樹。採用歸併排序的思想倒是很快,每次比較都需要比較o n 次,一共log2k次 package main import fmt type listnode struct func printlist...