int f(int n)
{
if (n <= 1)
{
return 1;
}
return f(n - 1) + f(n - 1);
}
私は、時間の複雑さがO(2^n)
であることを知っています。なぜか分かります。このコードの領域の複雑さは?
しかし、なぜ空間の複雑さがO(n)
であるのかわかりません。 いつもノードはn
個しかありませんが、それは私には意味がないと言われました。
int f(int n)
{
if (n <= 1)
{
return 1;
}
return f(n - 1) + f(n - 1);
}
私は、時間の複雑さがO(2^n)
であることを知っています。なぜか分かります。このコードの領域の複雑さは?
しかし、なぜ空間の複雑さがO(n)
であるのかわかりません。 いつもノードはn
個しかありませんが、それは私には意味がないと言われました。
第2のf(n-1)
は、最初のものが完了するまで実行できません(またその逆も同じです)。最初のコールはn
回回帰し、すべてのコールが返されるので、合計でn
のスタックフレームがプッシュされます。その後、2回目の呼び出しで同じことが行われます。
したがって、再帰で深度がn
以上になることはありません。これは、空間の複雑さに貢献する唯一の要因です。
しかし、あなたはそれをどのように知っていますか?(メモリ(n)= 1 + max(メモリ(n-1)これは、オペレーティングシステムが再帰を実装する方法です。潜在的にスレッドごとにそれぞれの呼び出しを実行することができます。それぞれが他の2つを待つ...私は、最悪の場合、なぜO(n)以上になるのか理解できません。一般的なケースではO(n)となることがあります。 – chris
複雑さの計算は理論的なものであり、具体的な実装に基づいているわけではないので、概念的には逐次再帰呼び出しで単一スレッドしか必要ありません。実際のスレッドを使用してコードを書き直すと、複雑さは異なります。 – Barmar
しかし、これは私の要点です。特定の実装に基づいていないため、最悪の場合のシナリオを考慮する必要があります。ではない? – chris
反復の一方の側が葉に達して戻ってくるまで、経路複雑さはO(n)であり、反復の反対側でも同様のことが起こり、すべての中間ステップで再帰で使用される領域は再帰木の深さのOより大きくなければならない。
指数時間複雑度ツリーを描画し、ツリーのルートからのリーフのパスの長さは線形になります。 この直線パスは、アルゴリズムの空間複雑度です。アルゴリズムは、問題を解決するためにそれらのパスのそれぞれをトラバースしますが、スタックに格納されている再帰呼び出しの最大数はリニアになります。例:f(3)
3
/ \
2 2
/\ /\
1 1 1 1
のルートからリーフへの最大長はO(n)
あります。従って、空間の複雑さもO(n)
である。
なぜ、左右のサブツリーに異なる値がありますか?それらは両方ともパラメーターとして 'n-1'で呼び出されます。多分フィボナッチを計算していると思ったのでしょうか? – Barmar
数式を書き、それを解く。 –
この質問は、http://cs.stackexchange.com/に適しています。 – Nayuki