[英]Big o notation and recursive functions
我正在尝试学习Big-O符号,但我很难计算递归函数的时间复杂度。
你能帮我理解下面例子的时间复杂度吗?
public int recursiveFunction(int n) {
if (n == 0) {
return 0;
}
return Math.max(recursiveFunction(rand(n)) + 2,recursiveFunction(n - 1));
}
public int rand(int n) {
return new Random().nextInt(n - 1);
}
谢谢。
时间将取决于rand(n)
返回的内容,但如果你采取最坏的情况,这将是n-2
。 所以代码简化为:
public int recursiveFunction(int n) {
if (n == 0) {
return 0;
}
return Math.max(recursiveFunction(n - 2) + 2,recursiveFunction(n - 1));
}
其渐近上界等于:
public int recursiveFunction(int n) {
if (n == 0) {
return 0;
}
recursiveFunction(n-1);
recursiveFunction(n-1);
return 0;
}
这是一个深度为n
且分支因子为2
的递归,因此O(2 ^ n)时间复杂度。
递归函数不是开始学习复杂性的好地方。 即使是相对简单的递归函数也需要非常复杂的计算来确定复杂性。
对于recursiveFunction(n)
,可以调用recursiveFunction(n-1)
和recursiveFunction(a)
,其中a < n-1
,所以最坏的是recursiveFunction(n-1)
一次和recursiveFunction(n-2)
一次。 这与Fibonacci系列具有相同的复杂性, 其复杂度为O(2 ^ n) 。 您会注意到链接中的算法与您的算法非常相似。
您无法理解代码的问题。 因为您的代码会创建随机值,所以无法确定其运行时复杂性。 由于你的'+2'和'-1',程序也可能永远不会结束。 然而,这不可能但是可能,因此人们只能说它是O(无限)。
bigO表示法的常见情况:
你只有一个循环:
for(int k=0;k<n;++k) {}
这是O(n),因为你有n次迭代
两个或多个循环顺序:
for(int k=0;k<n;++k) {}
for(int l=0;l<n;++l) {}
来到O(2 * n),但常量在bigO上无关紧要,所以它是O(n)
纠缠循环:
for(int k=0;k<n;++k) {
for(int l=0;l<n;++l) {
}
}
是O(n²),
for(int k=0;k<n;++k) {
for(int l=0;l<n;++l) {
for(int m=0;m<n;++m) {
}
}
}
是O(n³)等等
您将在搜索/比较算法中遇到的最常见的复杂性是
for(int k=0;k<n;++k) {
for(int l=k;l<n;++l) {// note here: l=k instead of l=0
}
}
是O(n * log(n))
有关详细信息,请使用谷歌。
你在这里选择了一个相当棘手的问题。 使用Math.Max计算并不重要,重要的是两个递归调用。
当n == 1时有一个问题,因为你调用rand(1),调用Random()。nextInt(0)没有定义 - 它应该返回一个随机整数,> = 0和<0,这是不可能。 让我们希望它返回0 - 如果不是,我们就麻烦了。
recursiveFunction(n)调用recursiveFunction(n - 1),并使用随机i,0 <= i <= n - 2进行另一次调用recursiveFunction(i)。让我们创建一个表,其中包含最大调用次数,计数1表示初始调用(假设rand(1)返回0,每隔一个调用返回n - 2):
n = 0: 1 calls
n = 1: 1 + 1 + 1 = 3 calls
n = 2: 1 + 1 + 3 = 5 calls
n = 3: 1 + 3 + 5 = 9 calls
n = 4: 1 + 5 + 9 = 15 calls
n = 5: 1 + 9 + 15 = 25 calls
n = 6: 1 + 15 + 25 = 41 calls
n = 7: 1 + 25 + 41 = 67 calls
n = 8: 1 + 41 + 67 = 109 calls
n = 9: 1 + 67 + 109 = 177 calls
n = 10: 1 + 109 + 177 = 287 calls
呼叫数量增长很快,但不如2 ^ n快。 我会说它是O(c ^ n),c = sqrt(1.25)+ 0.5。 那是最糟糕的情况; 平均水平要少得多。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.