23 合併K個排序鍊錶

2021-09-24 09:10:53 字數 3753 閱讀 8938

合併 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...