【问题标题】:Determining Time Complexity of a Recursive Function Calling From inside a Loop确定从循环内部调用递归函数的时间复杂度
【发布时间】:2019-02-21 20:52:19
【问题描述】:

我不确定,之前在 SO 中是否提出过这个问题。好吧,我正在检查数组中字符的频率。我在确定复杂性方面相当薄弱,所以我认为这个社区可以帮助我明白这一点!非常抱歉,如果我以一些抽象的形式发布它!如果有人可以帮助我,那就太好了!

这是我的代码:

class SearchAChar{
private static int getOccurance(char [] a, char k, int l, int r, int count){
    if(l == r) return count;

    if(a[l] == k){a[l]='0';count++;}

    return getOccurance(a, k, l+1, r, count);   
}
public static void main(String [] args){
    char [] arr = {'a', 'e', 'b', 'c', 'b', 'c', 'd','a'};

    for(int i=0; i<arr.length; i++){
        if(arr[i] == '0') continue;
        System.out.println("Occurance of : " +arr[i] + " is "+ getOccurance(arr, arr[i], i, arr.length, 0) +" times!");
    }
}
}

这个问题的运行时复杂度应该是多少?

【问题讨论】:

  • 似乎是线性的。
  • 是的!它只是线性的! :D
  • 请注意,使用地图,您可以使用 O(n) 而不是 O(n²)

标签: java algorithm time-complexity frequency


【解决方案1】:

由于有一个 for 循环,并且在 for 循环内部有一个递归函数,其运行时间复杂度为 O(n),因此最坏的时间复杂度为 O(n^2),其中 n 是字符数组。

【讨论】:

    【解决方案2】:

    让我们尝试分解;我说的是最坏情况的复杂性。

    n = length of the array

    1. for(int i=0; i&lt;arr.length; i++){} - 这不会循环 n 次,因为您通过在递归函数中将 seen char 设置为 0 来更新数组。如果 char 是 0 你继续。所以就像O(n/2)

    2. getOccurance(a, k, l+1, r, count) - 在每个字符上递归,直到长度为 == 增量。 表示递归函数调用堆栈的最佳方式是树。例如,此图像显示了如何构建调用堆栈来计算斐波那契。

    但是您的 getOccurance 函数不会像上面的斐波那契函数图片那样调用自身两次。所以我们可以说它有像树的一个分支一样的调用。换句话说,这里我们看到调用堆栈序列就像0,1,2... n-1,因此,我们可以计算复杂度O(n)

    如果我们把这两个步骤放在一起,我们就会得到。 O(n/2 * n)

    但也正如@Coderino 所提到的 - 在最坏的情况下不考虑非主导术语。

    综上所述,以上代码的复杂度为O(n^2)

    一些有用的资源 - https://users.cs.duke.edu/~ola/ap/recurrence.html

    Complexity of recursive factorial program

    【讨论】:

    • getOc​​curance 可以很容易地改写成一个线性循环;这绝不可能是远程O(2^n)
    • @CoderinoJavarino 你可能会重写它,但这不是一个线性循环,你能详细说明一下吗?
    • 递归和循环具有相同的功能,并且每个都可以被重写为具有相同复杂性的另一个等价物。这是一个普通的本地count var,以及一个简单的for (i = l; i &lt;=r; i++) 循环,它根据a[i] 有条件地递增它
    • @CoderinoJavarino 您正在发表一般性声明。这与问题中的 OP 代码有何关系?当然,它是有条件的循环,但不是递归调用。这就是为什么我说循环不是 `O(n)。
    • @LaksithaRanasingha 非常感谢您提供时间和详细的解释! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 1970-01-01
    • 2018-02-10
    相关资源
    最近更新 更多