したがって、ネストされたforループの数だけで、n ^ cの複雑さを持つアルゴリズムが何であるかを想像できます。
for (var i = 0; i < dataset.len; i++ {
for (var j = 0; j < dataset.len; j++) {
//do stuff with i and j
}
}
ログは毎回データセットを半分に分割するもので、バイナリ検索はこれを行います(このコードがどのように見えるかは完全にはわかりません)。
しかし、c ^ nまたはより具体的には2 ^ nであるアルゴリズムの簡単な例は何ですか。 O(2 ^ n)はデータのループに基づいていますか?または、データはどのように分割されますか?それとも完全に何か?
実行時間O(2 ^ N)のアルゴリズムは、サイズN-1の2つの小さな問題を再帰的に解くことにより、サイズNの問題を解決する再帰的アルゴリズムであることがよくあります。
このプログラムは、たとえば、擬似コードのN個のディスクの有名な「ハノイの塔」問題を解決するために必要なすべての動きを出力します。
_void solve_hanoi(int N, string from_peg, string to_peg, string spare_peg)
{
if (N<1) {
return;
}
if (N>1) {
solve_hanoi(N-1, from_peg, spare_peg, to_peg);
}
print "move from " + from_peg + " to " + to_peg;
if (N>1) {
solve_hanoi(N-1, spare_peg, to_peg, from_peg);
}
}
_
T(N)をN個のディスクにかかる時間とします。
我々は持っています:
_T(1) = O(1)
and
T(N) = O(1) + 2*T(N-1) when N>1
_
最後の用語を繰り返し展開すると、次のようになります。
_T(N) = 3*O(1) + 4*T(N-2)
T(N) = 7*O(1) + 8*T(N-3)
...
T(N) = (2^(N-1)-1)*O(1) + (2^(N-1))*T(1)
T(N) = (2^N - 1)*O(1)
T(N) = O(2^N)
_
これを実際に把握するには、繰り返し関係の特定のパターンが指数関数的な結果につながることを知る必要があります。通常、T(N) = ... + C*T(N-1)
は_C > 1
_でO(x ^ N)を意味します。見る:
たとえばセットのすべての可能なサブセットを反復処理します。この種のアルゴリズムは、一般的なナップザック問題などに使用されます。
サブセットの反復がO(2 ^ n)に変換される方法を理解するのが難しい場合は、n個のスイッチのセットを想像してください。各スイッチはセットの1つの要素に対応しています。これで、各スイッチをオンまたはオフにできます。 「オン」はサブセット内にあると考えてください。可能な組み合わせの数に注意してください:2 ^ n。
コードで例を参照したい場合、ここでは再帰について考えるのが通常は簡単ですが、od他のニースで不安定な例は今のところ考えられません。
int Fibonacci(int number)
{
if (number <= 1) return number;
return Fibonacci(number - 2) + Fibonacci(number - 1);
}
入力データセットへの追加ごとに成長が倍増します。 O(2N)関数の成長曲線は指数関数的です-非常に浅いところから始まり、その後、気象的に上昇します。
public void solve(int n, String start, String auxiliary, String end) {
if (n == 1) {
System.out.println(start + " -> " + end);
} else {
solve(n - 1, start, end, auxiliary);
System.out.println(start + " -> " + end);
solve(n - 1, auxiliary, start, end);
}
この方法では、プログラムは「ハノイの塔」問題を解決するためにすべての動きを印刷します。どちらの例も再帰を使用して問題を解決しており、O(2 ^ n)の実行時間が長くなりました。
c ^ N = n
サイズのアルファベットのc
要素のすべての組み合わせ。
より具体的には、2 ^ NはすべてNビットで表現可能な数値です。
一般的なケースは、次のような再帰的に実装されます。
vector<int> bits;
int N
void find_solution(int pos) {
if (pos == N) {
check_solution();
return;
}
bits[pos] = 0;
find_solution(pos + 1);
bits[pos] = 1;
find_solution(pos + 1);
}
以下は、goods配列のすべての値の組み合わせの値の合計を計算するコードクリップです(value
はグローバル配列変数です)。
fun boom(idx: Int, pre: Int, include: Boolean) {
if (idx < 0) return
boom(idx - 1, pre + if (include) values[idx] else 0, true)
boom(idx - 1, pre + if (include) values[idx] else 0, false)
println(pre + if (include) values[idx] else 0)
}
ご覧のとおり、再帰的です。ループを挿入してPolynomial
の複雑度を取得し、再帰を使用してExponential
の複雑度を取得できます。
python Big O/Landau(2 ^ N)の2つの簡単な例を示します。
#fibonacci
def fib(num):
if num==0 or num==1:
return num
else:
return fib(num-1)+fib(num-2)
num=10
for i in range(0,num):
print(fib(i))
#tower of Hanoi
def move(disk , from, to, aux):
if disk >= 1:
# from twoer , auxilart
move(disk-1, from, aux, to)
print ("Move disk", disk, "from rod", from_rod, "to rod", to_rod)
move(disk-1, aux, to, from)
n = 3
move(n, 'A', 'B', 'C')