繁体   English   中英

大写符号和递归函数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM