次のようなソートされた番号を持つテーブルがあります。
1 320102
2 5200100
3 92010023
4 112010202
5 332020201
6 332020411
:
5000000000 3833240522044511
5000000001 3833240522089999
5000000002 4000000000213312
レコード番号を考えると、O(log n) 時間の値が必要です。レコード番号は 64 ビット長であり、欠落したレコード番号はありません。値は 64 ビット長で、並べ替えられており、value(n) < value(n+1) です。
明らかな解決策は、単純に配列を作成し、レコード番号をインデックスとして使用することです。これには、値ごとに 64 ビットのコストがかかります。
しかし、それを行うには、よりスペース効率の良い方法が必要です。値が常に増加していることはわかっているので、それは実行できるはずですが、それを可能にするデータ構造を覚えていません。
解決策は、配列で deflate を使用することですが、要素にアクセスするために O(log n) が得られないため、受け入れられません。
私に与えるデータ構造を知っていますか:
- O(log n) アクセス
- スペース要件 < 64 ビット/値
= 編集 =
すべての数値が事前にわかっているため、各数値の違いを見つけることができます。これらの差の 99 パーセンタイルを取ると、比較的控えめな数値が得られます。log2 を取ると、適度な数を表すのに必要なビット数が得られます。これを適度なビットと呼びましょう。
次に、これを作成します。
64-bit value of record 0
64-bit value of record 1024
64-bit value of record 2048
64-bit value of record 3072
64-bit value of record 4096
次に、すべてのレコードのデルタ テーブル:
modest-bits difference to record 0
modest-bits difference to previous record
1022 * modest-bits difference to previous record
modest-bits difference to record 1024
k*1024 を記録するためのささやかなビットの差は常に 0 になるため、シグナリングに使用できます。ゼロ以外の場合、次の 64 ビットは、64 ビット値として次の 1024 レコードの単純な配列へのポインターになります。
控えめな値が 99 パーセンタイル数として選択されるため、それは多くても 1% の確率で発生するため、多くても 1% * n * 控えめなビット + 1% * n * 64 ビット * 1024 が無駄になります。
スペース: O(ささやかなビット * n + 64 ビット * n / 1024 + 1% * n * ささやかなビット + 1% * n * 64 ビット * 1024)
ルックアップ: O(1 + 1024)
(99% と 1024 は調整が必要な場合があります)
=編集2 =
上記のアイデアに基づいていますが、無駄なスペースが少なくなります。これを作成します。
64-bit value of record 0
64-bit value of record 1024
64-bit value of record 2048
64-bit value of record 3072
64-bit value of record 4096
そして、modest-bits で表すことができないすべての値に対して、big-value テーブルをツリーとして作成します。
64-bit position, 64-bit value
64-bit position, 64-bit value
64-bit position, 64-bit value
次に、1024 レコードごとにリセットされるすべてのレコードのデルタ テーブル:
modest-bits difference to record 0
modest-bits difference to previous record
1022 * modest-bits difference to previous record
modest-bits difference to record 1024
大きな値のテーブルにあるすべての値に対してもリセットされます。
スペース: O(控えめなビット * n + 64 ビット * n / 1024 + 1% * n * 2 * 64 ビット)。
ルックアップでは、大きな値のテーブルを検索し、次に 1024 番目の値を検索し、最後に適度なビット値を合計する必要があります。
ルックアップ: O(log(大きな値のテーブル) + 1 + 1024) = O(log n)
これを改善できますか?それとも別の方法でうまくやりますか?