QuickSelect實際上是一種分區算法,所以在QuickSelecting之後不需要額外的步驟。
讓我們假設我們有一個功能分區(ARR,LO,HI)返回一些k
這樣lo <= k < hi
和重新排列arr
這樣arr[i] <= arr[k]
如果i < k
和arr[k] <= arr[i]
如果k < i
。然後,在本質上,QuickSelect是:
# After this call:
# arr[i] <= arr[med] if lo <= i < med
# arr[med] <= arr[i] if med < i < hi
QuickSelect(arr, lo, med, hi):
if lo < hi:
k = Partition(arr, lo, hi)
if med < k:
QuickSelect(arr, lo, med, k)
else if k < med:
QuickSelect(arr, k + 1, med, hi)
這是非常相似的快速排序:
QuickSort(arr, lo, hi):
if lo < hi:
k = Partition(arr, lo, hi)
QuickSort(arr, lo, k)
QuickSort(arr, k + 1, hi)
由於QuickSelect分割在指定點的數組(不僅僅是找到關元多一點)中,我們可以很容易分層次定義爲QuickSelect重複呼叫:
Stratify(arr, n, p):
for i from 0 to p - 2 (inclusive):
QuickSelect(arr, floor(i * n/p), floor((i+1) * n /p, n)
由於QuickSelect是O(n)
,上述分層次是O(p*n)
。僅對數組進行排序的選項將需要O(n log n)
,因此如果p
不在O(log n)
中,則上面的Stratify非常有用。 (由於log n
是一個很小的數字,所以在實踐中很可能是優先排序)。
但是,很容易將分層結合到QuickSelect中,我們可以將它稱爲QuickStratify。 QuickStratify做了快速排序恰好到其中陣列是分層的點:
爲了方便起見,它報告的功能,其地層的給定索引落入:
Stratum(i, n, p): floor(i * p/n)
目前:
QuickStratify(arr, n, p, lo, hi):
if Stratum(lo, n, p) < Stratum(hi, n, p):
k = Partition(arr, lo, hi)
QuickStratify(arr, n, p, lo, k)
QuickStratify(arr, n, p, k + 1, hi)
我很確定QuickStratify的平均時間爲O(n log p)
,但我沒有證明方便,我可能是錯的。
舉個例子,是[[0],[1],[4,8,7,9,3,6,2,5]]是一個有效的輸出嗎?它可以在O(p * n)時間中找到,找到p-1個最小的元素,並將每個元素放入一個單獨列表中,其餘元素放在最終列表中。如果它無效,則說明您的問題不明確。 – chepner
好點。目的是讓輸出列表具有相同大小的+/- 1個元素。更新問題。 – user12341234