web-dev-qa-db-ja.com

O(n)数値のコレクションの中央値を見つけるアルゴリズム

問題:入力は(必ずしもソートされているわけではない)シーケンスS = k1、k2、...、knの任意の数です。 1 <= i、j <= nの場合、min {ki、kj}の形式のn²数のコレクションCを考えます。 O(n) timeおよびO(n) spaceアルゴリズムを提示して、Cの中央値を見つけます。

これまでのところ、異なるセットSのCを調べることで、CのSの最小数のインスタンスの数は(2n-1)、次に最小の数:(2n-3)などに等しいことがわかりました。最大数のインスタンスは1つだけです。

この情報を使用してCの中央値を見つける方法はありますか?

39
ejf071189

多くの可能性があります。私が気に入っているのは、HoareのSelectアルゴリズムです。基本的な考え方は、クイックソートに似ていますが、再帰するときは、探している番号を保持するパーティションにのみ再帰するという点が異なります。

たとえば、100個の数値の中央値が必要な場合は、Quicksortの場合と同様に、配列を分割することから始めます。 2つのパーティションを取得します。そのうちの1つには50個のパーティションが含まれます番目 素子。そのパーティションで選択を再帰的に実行します。パーティションに中央値となる要素が1つだけ含まれるまで続行します(また、選択した別の要素についても同じことができることに注意してください)。

19
Jerry Coffin

はい、良いパズルです。私たちはあなたが言った線で発達している中央値を見つけることができます。

Cでは、max(k)が1回発生し、次に高い3回発生し、次に高い5回発生します。

  1. Cの要素を順序付けた場合、m番目に大きい数の左側の要素数はm ^ 2(奇数の合計)です。

  2. 関心のある数値(中央値を計算するため)a。 nが奇数の場合、(n ^ 2 + 1)/ 2 =アルファbです。 nが偶数の場合、alpha1 = n ^ 2/2およびalpha2 = n ^ 2/2 + 1であるが、alpha1 = n ^ 2/2が2乗数になることはありません=> alpha1のすぐ右側の数はalpha1(最初のm個の奇数の合計は二乗)=> alpha1 = alpha2.

  3. つまり、m ^ 2(最初のm個の奇数の合計)が(n ^ 2/2)よりもちょうど高くなるようにmを決定することになります。

  4. つまり、m = ceiling(n/sqrt(2)と元のシーケンスのm番目の最大数を決定することになります(m番目の最高または(n-m-1)番目の最低を見つけるかどうかは最適化です)。

  5. 簡単にm番目の最大数を見つけることができます(左から最初のm個の最大数に注意してください)。

9
Om Deshmane

ウィキペディアには 選択アルゴリズム に関する良い記事があります。 C++を使用している場合、STLには nth_element() 平均線形時間のアルゴリズムが含まれています。

6
Blastfurnace