我正在尝试学习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);
}
感谢。
答案 0 :(得分:5)
时间将取决于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)时间复杂度。
答案 1 :(得分:3)
递归函数不是开始学习复杂性的好地方。即使是相对简单的递归函数也需要非常复杂的计算来确定复杂性。
对于recursiveFunction(n)
,您拨打recursiveFunction(n-1)
和recursiveFunction(a)
a < n-1
,最差为recursiveFunction(n-1)
一次,recursiveFunction(n-2)
一次。这与Fibonacci系列it's complexity is O(2^n)具有相同的复杂性。您会注意到链接中的算法与您的算法非常相似。
答案 2 :(得分:0)
您无法理解代码的问题。因为您的代码会创建随机值,所以无法确定其运行时复杂性。由于你的'+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))
有关详细信息,请使用Google。
答案 3 :(得分:0)
你在这里选择了一个相当棘手的问题。 Math.Max的计算并不重要,重要的是两个递归调用。
当n == 1时出现问题,因为你调用了rand(1),它调用了Random()。nextInt(0),它没有被定义 - 它应该返回一个随机整数,它是&gt; = 0且&lt; 0这是不可能的。让我们希望它返回0 - 如果不是,我们就麻烦了。
recursiveFunction(n)调用recursiveFunction(n - 1),并使用随机i,0&lt; = i&lt; = 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。这是最糟糕的情况;平均水平要少得多。