Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 递归算法的时间复杂度_C_Algorithm_Time Complexity - Fatal编程技术网

C 递归算法的时间复杂度

C 递归算法的时间复杂度,c,algorithm,time-complexity,C,Algorithm,Time Complexity,如何计算递归算法的时间复杂度 int pow1(int x,int n) { if(n==0){ return 1; } else{ return x * pow1(x, n-1); } } int pow2(int x,int n) { if(n==0){ return 1; } else if(n&1){ int p = pow2(x, (n-1)/2)

如何计算递归算法的时间复杂度

int pow1(int x,int n) {
    if(n==0){
        return 1;
    }
    else{
        return x * pow1(x, n-1);
    }
}

int pow2(int x,int n) {
    if(n==0){
        return 1;
    }
    else if(n&1){
        int p = pow2(x, (n-1)/2)
        return x * p * p;
    }
    else {
        int p = pow2(x, n/2)
        return p * p;
    }
}

它可能有点复杂,但我认为通常的方法是使用。

忽略递归的两个函数的复杂度都是O(1)

对于第一种算法,pow1(x,n)的复杂度为O(n),因为递归深度与n线性相关


第二个复杂度是O(logn)。这里我们递归大约log2(n)次。抛出2我们得到log n.

所以我猜你把x提升到n的幂。pow1取O(n)


您永远不会更改x的值,但每次从n中取1,直到它变为1(然后返回),这意味着您将进行n次递归调用。

让我们从pow1开始,因为这是最简单的调用

您有一个函数,其中一次运行在O(1)中完成。(条件检查、返回和乘法是恒定时间。)

剩下的就是递归。您需要做的是分析函数最终调用自身的频率。在pow1中,它将发生N次。N*O(1)=O(N)

对于pow2,这是相同的原理-函数的一次运行在O(1)中运行。然而,这次你每次都要把N减半。这意味着它将运行log2(N)次——有效地每比特运行一次。log2(N)*O(1)=O(logn)

可能对您有所帮助的是利用递归总是可以表示为迭代的事实(不总是非常简单,但这是可能的。我们可以将pow1表示为

result = 1;
while(n != 0)
{
  result = result*n;
  n = n - 1;
}

现在你有了一个迭代算法,你可能会发现用这种方法分析它更容易。

分析递归函数(甚至计算它们)是一项不平凡的任务。在我看来,Don Knuths中有一个很好的介绍

但是,现在让我们分析这些示例:

我们定义了一个函数,它给出函数所需的时间。假设
t(n)
表示
pow(x,n)
所需的时间,即
n
的函数

然后我们可以得出结论,
t(0)=c
,因为如果我们调用
pow(x,0)
,我们必须检查(
n==0
),然后返回1,这可以在常数时间内完成(因此常数
c

现在我们考虑另一种情况:<代码> n>0 < /代码>。这里我们得到了代码>t(n)=d+t(n-1)< /c>。这是因为我们再次检查<代码> n== 1 < /C>,计算<代码> POW(x,n-1)/代码>,因此(<代码> t(n-1)< /代码>),并将结果乘以<代码> x>代码>。检查和乘法可以在固定时间(常数<代码> d< /代码>)完成。,对
pow
的递归计算需要
t(n-1)

现在我们可以“扩展”术语
t(n)

那么,我们需要多长时间才能达到
t(1)
?因为我们从
t(n)
开始,每一步减去1,我们需要
n-1
步才能达到
t(n-(n-1))=t(1)
。另一方面,这意味着我们得到
n-1
乘以常数
d
,和
t(1)
的计算结果为
c

因此,我们得到:

t(n) =
...
d + d + d + ... + c =
(n-1) * d + c
所以我们得到了
t(n)=(n-1)*d+c
,这是O(n)的元素

pow2
可以使用。因为我们可以假设算法的时间函数是单调递增的。所以现在我们有了计算
pow2(x,n)
所需的时间
t(n)

对于
n>0
我们得到

        / t((n-1)/2) + d if n is odd  (d is constant cost)
t(n) = <
        \ t(n/2) + d     if n is even (d is constant cost)
/t((n-1)/2)+d如果n为奇数(d为固定成本)
t(n)=<
\t(n/2)+d,如果n为偶数(d为常数成本)
上述内容可“简化”为:

t(n)=floor(t(n/2))+d两个函数的复杂度都是O(1)-什么?忽略递归调用是O(1),但可以用不同的方式表示。关键是总复杂度完全取决于递归深度。
t(0) = c (since constant time needed for computation of pow(x,0))
        / t((n-1)/2) + d if n is odd  (d is constant cost)
t(n) = <
        \ t(n/2) + d     if n is even (d is constant cost)
t(n) = floor(t(n/2)) + d <= t(n/2) + d (since t is monotonically increasing)