数値のグループでN番目に大きい値を見つけるために必要なプログラムを書いています。これらの番号はプログラムによって生成されますが、N個の番号を保存するのに十分なメモリがありません。ストレージで達成できるNよりも優れた上限はありますか?数値のグループのサイズ(およびN)の上限は約1億です。
注:数値は小数であり、リストに重複を含めることができます。
[編集]:私のメモリ制限は16MBです。
数値のグループでN番目に大きい値を見つけるために必要なプログラムを書いています。これらの番号はプログラムによって生成されますが、N個の番号を保存するのに十分なメモリがありません。ストレージで達成できるNよりも優れた上限はありますか?数値のグループのサイズ(およびN)の上限は約1億です。
注:数値は小数であり、リストに重複を含めることができます。
[編集]:私のメモリ制限は16MBです。
最初から同じグループの数字を再生成できますか? そうであれば、出力に対して複数のパスを作成できます。最大値を見つけることから始め、ジェネレーターを再起動し、それよりも小さい最大値を見つけて、ジェネレーターを再起動し、結果が得られるまでこれを繰り返します。
多くの数があり、多くのパスが必要になるため、実際のパフォーマンスキラーになるでしょう-しかし、メモリに関しては、2つの要素(現在の最大値と「制限」、数最後のパスで見つかった) とパス カウンター。
プライオリティ キューを使用して M 個の最大要素 (メモリに収まる M を選択) を見つけることで高速化でき、必要なパスの数を N/M に減らすことができます。
たとえば、15 個の数値のリストから 10 番目に大きい要素を見つける必要がある場合は、逆の方法で作業することで時間を節約できます。これは 10 番目に大きい要素であるため、この要素よりも 15-10=5 小さい要素があることを意味します。したがって、代わりに 6 番目に小さい要素を探すことができます。
これはマルチパス アルゴリズムです (したがって、同じリストを複数回生成するか、リストをセカンダリ ストレージに保存できる必要があります)。
最初のパス:
最初の後に渡します:
最後のパス:
例: 表示される範囲が 0.0 から 1000.0 の場合、ビンの範囲は次のようになります。
(- 0.0 - 100.0]
(100.0 - 200.0]
(200.0 - 300.0]
...
(900.0 - 1000.0)
数値が (100.0 - 2000.0] ビンにあることがカウントによってわかった場合、次のビンのセットは次のようになります。
(100.0 - 110.0]
(110.0 - 120.0]
etc.
別のマルチパスのアイデア:
バイナリ検索を実行するだけです。範囲の中間点を最初の推測として選択します。パスは、次の見積もりを決定するために上/下のカウントを実行するだけで済みます (カウントによって重み付けするか、コードを簡単にするために単純な平均を計算できます)。
これは別の質問に似ています-ソートせずに配列内のn番目に小さい要素を検索するCプログラム?-あなたがいくつかの答えを得るかもしれないところ。
ロジックは、N番目に大きい/小さい検索でも同様に機能します。
注:これがその複製であると言っているのではありません。
あなたはたくさんの(ほぼ10億?)数を持っているので、ここにスペース最適化のための別の方法があります。
数値が32ビット値に収まると仮定すると、約10億は32GBに近いスペースを必要とします。現在、約128MBの作業メモリーを購入できる場合は、これを1回のパスで実行できます。
私がよく理解していれば、プログラムの上限メモリ使用量はO(N)(おそらくN + 1)です。現在のX(これまでのところN番目に大きい値)よりも大きい生成値のリストを、低いものから順に維持できます。新しい大きな値が生成されるとすぐに、現在のXをリストの最初の要素に置き換えて、生成されたばかりの値をリスト内の対応する位置に挿入できます。
並べ替え-n| uniq-cおよびN番目はN番目の行である必要があります