実際、この問題は非常に興味深いものです。なぜなら、それは情報理論のフレームワークを再構築したものだからです。
20 個の数値が与えられると、最終的に 21 個のビンになります (< 最初のものと > 最後のものを含む)。
着信番号ごとに、これらの 21 個のビンの 1 つにマップします。このマッピングは比較によって行われます。比較ごとに 1 ビットの情報が得られます (< または >= -- 2 つの状態)。
したがって、入ってくる数値がどのビンに属しているかを判断するために 5 回の比較が必要だとすると、その数値を表すために 5 ビットを使用することと同じになります。
私たちの目標は、比較の数を最小限に抑えることです! それぞれが 21 の順序付けられたコード ワードに属する 100 万の数字があります。どうやってそれを行うのですか?
これはまさにエントロピー圧縮の問題です。
a[1]、.. a[20] を 20 の数字とします。
p(n) = pr { 着信番号は < n } とします。
次のように決定木を構築します。
Step 1.
let i = argmin |p(a[i]) - 0.5|
define p0(n) = p(n) / (sum(p(j), j=0...a[i-1])), and p0(n)=0 for n >= a[i].
define p1(n) = p(n) / (sum(p(j), j=a[i]...a[20])), and p1(n)=0 for n < a[i].
Step 2.
let i0 = argmin |p0(a[i0]) - 0.5|
let i1 = argmin |p1(a[i1]) - 0.5|
等々...
完了するまでに、次のようになります。
i, i0, i1, i00, i01, i10, i11, etc.
これらの i のそれぞれが、比較位置を示します。
したがって、アルゴリズムは次のようになります。
u = 入力番号とする。
if (u < a[i]) {
if (u < a[i0]) {
if (u < a[i00]) {
} else {
}
} else {
if (u < a[i01]) {
} else {
}
}
} else {
similarly...
}
したがって、i はツリーを定義し、if ステートメントはツリーを歩いています。ループに入れることもできますが、if を使って説明する方が簡単です。
たとえば、データが 0 から 2^63 の間で一様に分布していることがわかっていて、20 の数が
0,1,2,3,...19
それから
i = 20 (notice that there is no i1)
i0 = 10
i00 = 5
i01 = 15
i000 = 3
i001 = 7
i010 = 13
i011 = 17
i0000 = 2
i0001 = 4
i0010 = 6
i0011 = 9
i00110 = 8
i0100 = 12
i01000 = 11
i0110 = 16
i0111 = 19
i01110 = 18
基本的に、比較は次のようになります。
if (u < a[20]) {
if (u < a[10]) {
if (u < a[5]) {
} else {
...
}
} else {
...
}
} else {
return 21
}
ここで、二分探索を行っていないことに注意してください。私は最初に終点をチェックしています。なぜ?
100*((2^63)-20)/(2^63)% の確率で a[20] より大きくなります。これは基本的に 99.999999999999999783159565502899% の確率です!
したがって、このアルゴリズムでは、上記で指定されたプロパティを持つデータセットの予想比較数は 1 です。(これは log log :p よりも優れています)
ここで行ったことに注意してください。基本的に、可能性の高い数値を見つけるために少ない比較を使用し、可能性の低い数値を見つけるために多くの比較を使用していることに注意してください。たとえば、数値 18 には 6 回の比較が必要です (二分探索の場合よりも 1 回多い)。ただし、20 から 2^63 までの数値は 1 回の比較しか必要ありません。これと同じ原理がロスレス (エントロピー) データ圧縮に使用されます。頻繁に現れるコード ワードをエンコードするために、より少ないビットを使用します。
ツリーの構築は 1 回限りのプロセスであり、100 万回後にツリーを使用できます。
問題は...この決定木が二分探索になるのはいつですか? 宿題の練習!:p 答えは簡単です。これは、ファイルを圧縮できなくなった場合と似ています。
わかりました、だから私はこれを私の後ろから引き出しませんでした...基礎はここにあります:
http://en.wikipedia.org/wiki/Arithmetic_coding