heapq
の時間計算量はO(n個のログ)push
とOで、バイナリヒープあるかわからない、それではありません(logn)pop
。 heapq source codeを参照してください。
あなたが表示するアルゴリズムは、すべての項目をヒープにプッシュするためにO(n log n)、次にk番目に大きい要素を見つけるためにO((n-k)log n)を必要とします。したがって複雑さはO(n log n)になります。また、O(n)の余分なスペースが必要です。
O(n log k)では、O(k)余分なスペースを使用してアルゴリズムをわずかに修正することでこれを行うことができます。あなたは擬似コードを変換する必要がありますので、私は、Pythonプログラマではないよ。ここに
create a new min-heap
push the first k nums onto the heap
for the rest of the nums:
if num > heap.peek()
heap.pop()
heap.push(num)
// at this point, the k largest items are on the heap.
// The kth largest is the root:
return heap.pop()
キーは、ヒープがこれまで見てちょうど最大の項目が含まれていることです。アイテムがこれまでに見たk番目に大きいものよりも小さい場合は、決してヒープに置かれません。最悪の場合はO(n log k)です。
実は、heapq
はheapreplace
方法を持っているので、あなたがこれを置き換えることができます:
if num > heap.peek()
heap.pop()
heap.push(num)
また
if num > heap.peek()
heap.replace(num)
で、最初
k
アイテムをプッシュする代わりに、リストを作成することです最初に
k
のアイテムと
heapify
と呼んでください。より最適化された(それでもO(n個のkをログ))のアルゴリズムは、次のとおりです。
create array of first `k` items
heap = heapify(array)
for remaining nums
if (num > heap.peek())
heap.replace(num)
return heap.pop()
あなたはまた、最初n-k
アイテムをポップ、その後、配列全体にheapify
を呼び出し、その後トップを取ることができる:
heapify(nums)
for i = 0 to n-k
heapq.heappop(nums)
return heapq.heappop(nums)
これは簡単です。以前の提案より速いのかどうかはわかりませんが、元の配列が変更されています。複雑さは、ヒープを構築するためにO(n)であり、次にポップに対してO((n-k)log n)である。それはO((n-k)log n)です。最悪の場合O(n log n)。
"lgk"とは何ですか? –
@ValentinLorentz、 'lgx'は一般的に' log(x) 'を意味します。 – Dunes
もっと文脈が必要です。 'heapush()'と 'heapop()'の時間の複雑さを理解していますか? 4行目と5行目のループが非効率的であり、ルーチン全体が必要以上に効率が悪いことを理解していますか? –