我想寫一個最佳函數,給出一個項目列表,返回一個重新排序的列表與top_k項目在開始(他們不需要自己命令)。我對剩餘元素的順序沒有任何限制,但理想情況下我希望他們按原始順序排列。Python的性能:堆
我試過3種方法。首先,一個在O(top_k * N)時間運行的簡單解決方案。其次,使用O(log(top_k)* N)(最慢)的最大元素的優先級堆,最後通過強力排序整個列表O(N * logN),結果是最快的)
def semi_sort_trivial(items, top_k=3):
for i in range(top_k):
maximum = items[i]
pos = i
for j in range(i+1, len(itemss)):
if maximum < events[j]:
pos = j
maximum = items[j]
# Swap maximum with the top i'th position under evaluation.
items[pos], items[i] = items[i], items[pos]
return items
def semi_heap_sort(items, top_k=3):
lst = []
heap_store = items[:top_k]
for item in items[top_k:]:
lst.append(heapq.heappushpop(heap_store, item))
return heap_store + lst
def semi_sort_usingsort(items, top_k=3):
lst = sorted(items)[-top_k:]
return lst + [item for item in items if item not in lst]
In [7]: %timeit semi_heap_sort(range(20))
10000 loops, best of 3: 26.3 us per loop
In [8]: %timeit semi_sort_trivial(range(20))
100000 loops, best of 3: 11 us per loop
In [9]: %timeit semi_sort_usingsort(range(20))
100000 loops, best of 3: 5.89 us per loop
我很驚訝堆表現最差。我最初的猜測是恆定的因素太高。但在嘗試更大的範圍之後,我仍然遇到類似的性能問題。我期望堆能夠表現最好。任何指針?
感覺就像有一個更好的方法來解決這個問題。對於N = 20和k = 3的一般情況,N log N大約是20 * 5操作,我相信我們應該能夠在N log top_k或20 * 2操作中執行此操作。應該可以比semi_sort_usingsort方法做得更好。任何建議,使這種情況發生?
謝謝。
謝謝!這是非常有用的:-) – GeneralBecos 2011-05-24 02:38:19
只是發現你的優化版本有一個錯誤,剩菜數組將永遠是空的。 – GeneralBecos 2011-05-24 03:51:07
@GeneralBecos,實際上它的空的堆_store – 2011-05-24 14:00:26