私はランダム性に基づく非効率的なアルゴリズムについて考えていて、それらをどのように分類するのか疑問に思いました。
例えば。 1からNまでのすべての数値をランダムな順序で生成し、それぞれ1回だけ生成したいとします。
私の非効率なアルゴリズムはこれを行います...
Generate a random number between 1 and N (inclusive).
Check it has not already been used.
If it has then generate a new random number until you get one that hasn't been used.
Display the random number.
Store random number in checking array.
これにより、すべての数値がランダムな順序で取得されますが、Nの値が大きい場合、最後のいくつかの数値を取得するときに複数回実行する必要があります。
例えば。平均して、最後のランダム値の生成にはN回かかります。
生成される各乱数が異なる可能性があるため、これの最良のケースはO(N)です。
平均的なケースは少し難しいです...
適切に計算を行わなければ、O(NlogN)または可能なO(N ^ 2)だと思います。
しかし、最悪のケースは何でしょうか?さて、最悪のケースは、それがすべての数を見つけることができないということです。無限にループし、実際に完了することはありません。理解しやすい大きなNの場合、大きなO表記をどのように与えますか?
最悪のケースはO(∞)です。最良の場合はΩ(n2)、n個の数値を生成する必要があるため、生成された各数値について、その数がすでにそこにあるかどうかに関係なく、長さnのリストを検索する必要があります。
この問題は確率論的分析を用いて解決されると思います。そのため、選択した乱数がすでにリストに含まれている確率を考慮する必要があります。これを行うには、乱数ジェネレータについて、特に、一様な分布で数値を生成することを前提とする必要がある場合があります。つまり、1からNまでの任意の数値が等しく生成される可能性が高いということです。
したがって、最初に選択された数については、リストにまだ何もないため、すでに選択されている確率は0/n = 0です。 2番目の数は、その数がすでに選択されている確率は1/nです。これは、生成された各番号で続行されます。さらに、これらの確率のそれぞれにコストを関連付ける必要があります。数値がすでに選択されている確率に関連するコストと、選択されていない確率に関連するコストの両方を考慮する必要があります。
配列を作成する場合は、O(n)で実行されるわずかに変更されたアルゴリズムを使用できます。
Fill the array with the numbers from 1 to n.
Repeat for i = 0 to n - 1:
Generate a random number r such that 0 ≤ r < n - i.
Exchange array [i] and array [i + r]