如何在Java中找到递归方法的时间复杂性?

如何在Java中找到递归方法的时间复杂性?,java,recursion,big-o,time-complexity,Java,Recursion,Big O,Time Complexity,我还没有完全掌握复杂性的概念,我想知道我如何才能计算出这段代码中方法f(n)的复杂性: import java.util.Random; public class Main { public static void main(String[] args) { Random r = new Random(); r.setSeed(System.currentTimeMillis()); int n = r.nextInt(20) + 1; f(n); }

我还没有完全掌握复杂性的概念,我想知道我如何才能计算出这段代码中方法f(n)的复杂性:

import java.util.Random;

public class Main {
  public static void main(String[] args) {
    Random r = new Random();
    r.setSeed(System.currentTimeMillis());
    int n = r.nextInt(20) + 1;
    f(n);
  }

  private static void f(int n){
    if(n > 0){
      g(n);
      System.out.println();
      f(n-1);
    }
  }

  private static void g(int n){
    if(n > 0){
      System.out.print('X');
      g(n-1);
    }
  }
}

我知道这是一种递归方法,这让我很困惑。我看到每次调用函数f()时,都会调用g(),并运行n次,然后f()再次以n-1的形式调用自己,直到n=0。我不知道从哪里开始任何帮助都会很好。谢谢。

确定递归函数运行时的一种常用技术是写出递归关系,将运行时描述为根据自身定义的数量。让我们从g开始。如果让cn表示g(n)的运行时,那么

  • c0=1(调用g(0)需要恒定的工作量)
  • cn+1=cn+1(调用g(n)自己做恒定量的工作,然后调用g(n-1)
我们可以查看c的几个值,看看是否发现了一种模式:

  • c0=1
  • c1=c0+1=1+1=2
  • c2=c1+1=2+1=3
  • c3=c2+1=3+1=4
一般来说,它看起来像cn=n+1。如果你愿意的话,你可以用归纳法证明这一点,但现在我们要相信它。这意味着g的运行时间是O(n)

现在,让dn作为调用f(n)的运行时

  • d0=1(调用f(0)会执行恒定的工作量)
  • dn+1=dn+cn+1(调用f(n+1)调用g(n+1),需要cn+1工作,然后调用f(n)
我们可以把它展开,看看我们是否看到了一种模式

  • d0=1
  • d1=c1+d0=2+1
  • d2=c2+d1=3+2+1
  • d3=c3+d2=4+3+2+1

一般来说,它看起来像dn=n+(n-1)+(n-2)+…+1。如果你愿意的话,可以通过归纳法将其形式化。这是一个著名的总和,结果是n(n+1)/2。这个量恰好是Θ(n2),所以整个运行时是Θ(n2)。

首先,计算调用g()的次数,作为传递给f()的初始参数n的函数。这将为您提供函数所用的时间,即执行g()所用时间的倍数,不包括递归


然后删除系数和低阶项。例如,如果结果为0.5n^2+0.5n,则删除0.5n,因为它是低阶项-不是平方项-留下0.5n^2,然后删除0.5系数,留下n^2。这意味着函数在O(n^2)中运行时间。

虽然不是分析递归的一般策略,但您的
f(n)
本质上是一个循环,运行
g(k)
k
值跨越1到n。因此
f(n)
的运行时间本质上是
g(n)
g(n-1)
,…,
g(2)
g(1)的运行时间的总和

因为您已经知道
g(k)
的运行时间本质上是
k
,所以您的最终运行时间是从1到n的总和。如果您知道总和公式,您将知道其顺序是O(n2)