web-dev-qa-db-ja.com

O(klogk)バイナリヒープからk番目に小さい要素を見つける時間アルゴリズム

n個の異なるアイテム(ルートで最小のアイテム)を含むnノードのバイナリヒープがあります。 _k<=n_の場合、O(klogk)時間アルゴリズムを見つけて、ヒープからkth最小要素を選択します。

O(klogn)は明白ですが、O(klogk)を理解できませんでした。たぶん、2つ目のヒープを使用できます。

32
user978837

まあ、あなたの直感は、O(klogk)を達成するために追加のデータ構造が必要であるということは正しかったです。

目標とする複雑さO(klogk)から推測して、目標を達成するのに役立つサイズkのヒープを作成して維持したいと思います。ご存知かもしれませんが、サイズkのヒープをトップダウン方式で構築するには、O(klogk)が必要です。これは、私たちの目標を本当に思い出させます。

以下は、O(klogk)を達成するための私の試みです(必ずしもエレガントでも効率的でもありません)。

  1. 新しい最小ヒープを作成し、そのルートを元のヒープのルートに初期化します。

  2. 現在のルートを削除し、現在のルートの2つの子を元のヒープに挿入することにより、新しい最小ヒープを更新します。このプロセスをk回繰り返します。

  3. 結果のヒープはk個のノードで構成され、そのルートは元のヒープのk番目に小さい要素です。

注:新しいヒープのノードは、ノード値自体ではなく、対応するノードのインデックスを元のヒープに格納する必要があります。手順2の各反復で、新しいヒープに1つ以上のノードのネット(1つは削除、2つは挿入)を実際に追加します。k回の反復により、サイズkの新しいヒープが生成されます。 i番目の反復の間、削除されるノードは、元のヒープのi番目に小さい要素です。

時間の複雑さ:各反復で、1つの要素を削除して新しいヒープに2つ挿入するのにO(3logk)時間かかります。k回の反復後、O(3klogk) = O(klogk)。

このソリューションがあなたに少しインスピレーションを与えることを願っています。

27
Terry Li

ルートノードが常にその子ノードよりも小さくなるように、minheapを使用していると仮定します。

Create a sorted list toVisit, which contains the nodes which we will traverse next. This is initially just the root node.
Create an array smallestNodes. Initially this is empty.
While length of smallestNodes < k:
    Remove the smallest Node from toVisit
    add that node to smallestNodes
    add that node's children to toVisit

完了すると、k番目に小さいノードがleastNodes [k-1]に入ります。

ToVisitの実装に応じて、log(k)時間に挿入し、一定の時間に削除できます(最上位のノードのみを削除しているため)。これでO(k * log(k))が合計されます。

22
Kevin