[解決済み] heapqライブラリの関数の時間複雑性は?
質問内容
質問なのですが、下記のleetcodeの解答を見ると、なぜか
O(k+(n-k)log(k))
.
補足です。複雑さはそれほどでもないかもしれません、実際、私は
heappush()
と
heappop()
# O(k+(n-k)lgk) time, min-heap
def findKthLargest(self, nums, k):
heap = []
for num in nums:
heapq.heappush(heap, num)
for _ in xrange(len(nums)-k):
heapq.heappop(heap)
return heapq.heappop(heap)
解決方法は?
heapq
はバイナリヒープで、O(log n)である。
push
とO(log n)
pop
. を参照してください。
heapq ソースコード
.
あなたが示したアルゴリズムは、すべてのアイテムをヒープにプッシュするのに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 log k))アルゴリズムとしては
# create array of first `k` items
heap = heapify(array)
for remaining nums
if (num > heap.peek())
heap.replace(num)
return heap.pop()
を呼び出すこともできます。
heapify
を配列全体に適用し、最初の
n-k
のアイテムを取得し、その後、トップを取ります。
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)となります。
関連
-
[解決済み】DataFrameのコンストラクタが正しく呼び出されない!エラー
-
[解決済み】ilocが「IndexError: single positional indexer is out-of-bounds」を出す。
-
[解決済み】終了コード -1073741515 (0xC0000135)でプロセス終了)
-
[解決済み】django インポートエラー - core.managementという名前のモジュールがない
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで型をチェックする標準的な方法は何ですか?
-
[解決済み] 億の相対的輸入
-
[解決済み] リストとタプルの違いは何ですか?
-
[解決済み] 2次元アレイにおけるピーク検出
-
[解決済み] ヒープの構築はどうして時間計算量O(n)になるのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Pythonの学習とデータマイニングのために知っておくべきターミナルコマンドのトップ10
-
Python interpreted model libraryによる機械学習モデル出力の可視化 Shap
-
PythonによるExcelファイルの一括操作の説明
-
Python LeNetネットワークの説明とpytorchでの実装
-
[解決済み】RuntimeWarning: 割り算で無効な値が発生しました。
-
[解決済み】Python regex AttributeError: 'NoneType' オブジェクトに 'group' 属性がない。
-
[解決済み】OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。
-
[解決済み】TypeError: re.findall()でバイトのようなオブジェクトに文字列パターンを使用することはできません。)
-
[解決済み】TypeErrorを取得しました。エントリを持つ子テーブルの後に親テーブルを追加しようとすると、 __init__() missing 1 required positional argument: 'on_delete'
-
[解決済み】Python Error: "ValueError: need more than 1 value to unpack" (バリューエラー:解凍に1つ以上の値が必要です