web-dev-qa-db-ja.com

再帰関数の複雑さを判断する(Big O表記)

私は明日Computer Science Midtermを持っています、そして私はこれらの再帰的関数の複雑さを決定するのを手伝う必要があります。私は単純なケースを解決する方法を知っていますが、私はまだこれらのより難しいケースを解決する方法を学ぶことを試みています。これらは、私が理解できなかったほんの数例の問題です。どんな助けも大いに感謝され、私の研究に大いに役立つでしょう、ありがとう!

int recursiveFun1(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun1(n-1);
}

int recursiveFun2(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun2(n-5);
}

int recursiveFun3(int n)
{
    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun3(n/5);
}

void recursiveFun4(int n, int m, int o)
{
    if (n <= 0)
    {
        printf("%d, %d\n",m, o);
    }
    else
    {
        recursiveFun4(n-1, m+1, o);
        recursiveFun4(n-1, m, o+1);
    }
}

int recursiveFun5(int n)
{
    for (i = 0; i < n; i += 2) {
        // do something
    }

    if (n <= 0)
        return 1;
    else
        return 1 + recursiveFun5(n-5);
}
213
Michael_19

各関数のBig O表記での時間の複雑さは、番号順になっています。

  1. 最初の関数はベースケースに達する前にn回再帰的に呼び出されるので、そのO(n)はしばしばlinearと呼ばれます。
  2. 2番目の関数は毎回n-5と呼ばれるので、関数を呼び出す前にnから5を差し引きますが、n-5もO(n)です。 (実際にはn/5の次数と呼ばれる。そして、O(n/5) = O(n))。
  3. この関数は、関数を呼び出す前に5で除算するたびにlog(n)5進数になります。したがって、そのO(log(n))(5進数)は、しばしば対数と呼ばれ、ほとんどの場合、Big O表記と複雑度解析はbaseを使用します2。
  4. 4番目に、それはO(2^n)、または指数です、なぜならそれが再帰されない限り、各関数呼び出しはそれ自身を2回呼び出すからですn回。
  5. 最後の関数については、forループは2ずつ増えていくのでn/2、再帰はn-5となり、forループは再帰的に呼び出されるので(n-5)*(n/2)=(2n-10)* n = 2n ^ 2-10n、漸近的な振る舞いと最悪のシナリオの考慮事項、または大きなOが求めている上限のために、最大O(n^2)のみに関心があります。

    あなたの中期に頑張ってください;)

271
coder

再帰的アルゴリズムの複雑さを近似するために私が見つける最良の方法の1つは、再帰木を描くことです。再帰木ができたら:

Complexity = length of tree from root node to leaf node * number of leaf nodes
  1. 最初の関数の長さはn、リーフノードの数は1なので、複雑さはn*1 = nになります。
  2. 2番目の関数の長さはn/5、リーフノードの数は1なので、複雑さはn/5 * 1 = n/5になります。それはnに近似されるべきです

  3. 3番目の関数では、再帰呼び出しごとにnが5で除算されているため、再帰ツリーの長さはlog(n)(base 5)、リーフノードの数は1となり、複雑さはlog(n)(base 5) * 1 = log(n)(base 5)になります。

  4. 4番目の関数では、すべてのノードに2つの子ノードがあるため、リーフノードの数は(2^n)、再帰ツリーの長さはnになり、複雑さは(2^n) * nになります。しかし、n(2^n)の前では重要ではないため、無視することができ、複雑さは(2^n)としか言いようがありません。

  5. 5番目の機能については、複雑さを導入する2つの要素があります。関数の再帰的な性質によって導入される複雑さ、および各関数のforループによって導入される複雑さ。上記の計算を行うと、関数の再帰的な性質によってもたらされる複雑さは~ nとforループによる複雑さnになります。全体の複雑さはn*nになります。

注:これは複雑さを計算するための迅速で汚い方法です(公式なことは何もしていません!)これについてのフィードバックを聞きたいです。ありがとう。

18
Shubham