大写符号和递归函数

时间:2013-01-02 13:31:01

标签: java recursion big-o time-complexity

我正在尝试学习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);
}

感谢。

4 个答案:

答案 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。这是最糟糕的情况;平均水平要少得多。