Recursion 确定递归函数的复杂性(大O表示法)
明天我有一个计算机科学期中考试,我需要帮助确定这些递归函数的复杂性。我知道如何解决简单的案件,但我仍在努力学习如何解决这些较难的案件。这些只是我无法理解的几个示例问题。任何帮助都将不胜感激,并将对我的学习大有帮助,谢谢Recursion 确定递归函数的复杂性(大O表示法),recursion,big-o,complexity-theory,Recursion,Big O,Complexity Theory,明天我有一个计算机科学期中考试,我需要帮助确定这些递归函数的复杂性。我知道如何解决简单的案件,但我仍在努力学习如何解决这些较难的案件。这些只是我无法理解的几个示例问题。任何帮助都将不胜感激,并将对我的学习大有帮助,谢谢 int recursiveFun1(int n) { if (n <= 0) return 1; else return 1 + recursiveFun1(n-1); } int recursiveFun2(int n)
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);
}
intrecursivefun1(intn)
{
如果(n每个函数的时间复杂度,用大O表示法:
此函数每次调用n-5,因此我们在调用函数之前从n中减去5,但n-5也是O(n)
。
(实际称为n/5倍的顺序,并且,O(n/5)=O(n))
在这里,它是O(2^n)
,或者指数的,因为每个函数调用自己两次,除非它被递归n次
int递归函数5(int n)
{
对于(i=0;i 如果(n用于n=0
的情况
我们将在下面的部分中考虑案例<代码> n>=0 < /> >
一,
其中a是常数
通过归纳法:
T(n) = n * a + T(0) = n * a + b = O(n)
T(n) = ceil(n / 5) * a + T(k) = ceil(n / 5) * a + b = O(n)
T(n) = a * log5(n) + T(0) = a * log5(n) + b = O(log n)
T(n) = a + 2a + 4a + ... + 2^(n-1) * a + T(0) * 2^n
= a * 2^n - a + b * 2^n
= (a + b) * 2^n - a
= O(2 ^ n)
T(n) = T(5q + r)
= (5q + r) / 2 + (5 * (q - 1) + r) / 2 + ... + r / 2 + T(r)
= 5 / 2 * (q + (q - 1) + ... + 1) + 1 / 2 * (q + 1) * r + T(r)
= 5 / 4 * (q + 1) * q + 1 / 2 * (q + 1) * r + T(r)
= 5 / 4 * q^2 + 5 / 4 * q + 1 / 2 * q * r + 1 / 2 * r + T(r)
其中a,b是常数
二,
其中a是常数
通过归纳法:
T(n) = n * a + T(0) = n * a + b = O(n)
T(n) = ceil(n / 5) * a + T(k) = ceil(n / 5) * a + b = O(n)
T(n) = a * log5(n) + T(0) = a * log5(n) + b = O(log n)
T(n) = a + 2a + 4a + ... + 2^(n-1) * a + T(0) * 2^n
= a * 2^n - a + b * 2^n
= (a + b) * 2^n - a
= O(2 ^ n)
T(n) = T(5q + r)
= (5q + r) / 2 + (5 * (q - 1) + r) / 2 + ... + r / 2 + T(r)
= 5 / 2 * (q + (q - 1) + ... + 1) + 1 / 2 * (q + 1) * r + T(r)
= 5 / 4 * (q + 1) * q + 1 / 2 * (q + 1) * r + T(r)
= 5 / 4 * q^2 + 5 / 4 * q + 1 / 2 * q * r + 1 / 2 * r + T(r)
其中a,b是一些常数,k=T(r)
我找到的逼近递归算法复杂度的最佳方法之一是绘制递归树。一旦有了递归树:
Complexity = length of tree from root node to leaf node * number of leaf nodes
第一个函数的长度为n
,叶节点数为1
,因此复杂性为n*1=n
第二个函数的长度为n/5
,叶节点的数量为1
,因此复杂性为n/5*1=n/5
。应近似为n
对于第三个函数,因为在每次递归调用中,n
被除以5,递归树的长度将是log(n)(以5为基数)
,叶节点的数量再次为1,因此复杂性将是log(n)(以5为基数)*1=log(n)(以5为基数)
对于第四个函数,因为每个节点都有两个子节点,所以叶节点的数量将等于(2^n)
,递归树的长度将是n
,因此复杂性将是(2^n)*n
。但是因为n
在(2^n)之前是不重要的
,它可以被忽略,复杂性只能说是(2^n)
对于第五个函数,有两个元素引入复杂性。每个函数中函数的递归性质引入的复杂性和For
循环引入的复杂性。进行上述计算时,函数的递归性质引入的复杂性将是~n
和For循环引起的复杂性<代码>n
。总的复杂性将是n*n
注意:这是一种计算复杂性的快速而肮脏的方法(不是官方的!)。我很乐意听到有关这方面的反馈。谢谢。我们可以从数学上证明这一点,这是我在上述答案中遗漏的 它可以大大帮助您理解如何计算任何方法。 我建议从头到尾阅读,以充分了解如何做到这一点:
T(n)=T(n-1)+1
这意味着方法完成所需的时间与相同的方法相同,但n-1是T(n-1)
,我们现在添加+1
,因为它是完成一般操作所需的时间(除了T(n-1)
)。
现在,我们将发现
T(n-1)
如下:T(n-1)=T(n-1)+1
。看起来我们现在可以形成一个函数,它可以给我们一些重复,这样我们就可以完全理解了。我们将把T(n-1)=…
的右侧,而不是T(n-1)
放在方法T(n)中=…
这将给我们:T(n)=T(n-1-1)+1+1
这是T(n)=T(n-2)+2
,或者换句话说,我们需要找到我们缺少的k
:T(n)=T(n-k)+k
。下一步是采取n-k
,并声称n-k=1
,因为在递归结束时正好需要O(1)当n时,这里的关键是可视化调用树。一旦这样做,复杂性是:
nodes of the call tree * complexity of other code in the function
后一项的计算方法与我们对正规迭代函数的计算方法相同
相反,完整树的总节点计算为
C^L - 1
------- , when C>1
/ C - 1
/
# of nodes =
\
\
L , when C=1
其中C是每个节点的子节点数,L是树的级别数(包括根)
可视化树很容易。从第一次调用(根节点)开始,然后绘制与函数中递归调用数相同的子级数。将传递给子调用的参数作为“节点值”写入也很有用
因此,在上面的例子中:
这里的调用树是C=1,L=n+1。其余函数的复杂度是O(1)。因此,总复杂度是L*O(1)=(n+1)*O(1)=O(n)
这里的调用树是C=1,L=n/5。函数其余部分的复杂度是O(1)。因此总复杂度是L*O(1)=(n/5)*O(1)=O(n)
这里的调用树是C=1,L=log(n)。函数其余部分的复杂度是O(1)。因此,总复杂度是L*O(1)=log5(n)*O(1)=O(log(n))
这里的调用树是C=2,L=n。函数其余部分的复杂性是O(1)。
这次我们使用调用树中节点数的完整公式,因为C>1。因此总复杂度为(C^L-1)/(C-1)*O(1)=(2^n-1)*O(1)=O(2^n)
这里的调用树是C=1,L=n/5。函数其余部分的复杂度是O(n)。因此,总复杂度是L*O(1)=(n/5)*O(n)=O(n^2)
我看到了公认的答案(重复
T(n) = n / 2 + T(n - 5)
T(5q + r) = (5q + r) / 2 + T(5 * (q - 1) + r)
T(n) = T(5q + r)
= (5q + r) / 2 + (5 * (q - 1) + r) / 2 + ... + r / 2 + T(r)
= 5 / 2 * (q + (q - 1) + ... + 1) + 1 / 2 * (q + 1) * r + T(r)
= 5 / 4 * (q + 1) * q + 1 / 2 * (q + 1) * r + T(r)
= 5 / 4 * q^2 + 5 / 4 * q + 1 / 2 * q * r + 1 / 2 * r + T(r)
T(n) = T(5q + r)
= 5 / 2 * q^2 + (5 / 4 + 1 / 2 * r) * q + 1 / 2 * r + b
= 5 / 2 * O(n ^ 2) + (5 / 4 + 1 / 2 * r) * O(n) + 1 / 2 * r + b
= O(n ^ 2)
Complexity = length of tree from root node to leaf node * number of leaf nodes
nodes of the call tree * complexity of other code in the function
C^L - 1
------- , when C>1
/ C - 1
/
# of nodes =
\
\
L , when C=1
n level 1
n-1 level 2
n-2 level 3
n-3 level 4
... ~ n levels -> L = n
n
n-5
n-10
n-15
... ~ n/5 levels -> L = n/5
n
n/5
n/5^2
n/5^3
... ~ log5(n) levels -> L = log5(n)
n level 1
n-1 n-1 level 2
n-2 n-2 n-2 n-2 ...
n-3 n-3 n-3 n-3 n-3 n-3 n-3 n-3 ...
... ~ n levels -> L = n
n
n-5
n-10
n-15
... ~ n/5 levels -> L = n/5