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

use*_*380 7 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);
  }

  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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

我知道这是一种递归方法,令我感到困惑.我看到每次调用函数f()时,都会调用g()并运行n次,然后f()再次将自身称为n-1,直到n = 0.我不知道从哪里开始任何帮助都会很棒.谢谢.

tem*_*def 6

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

  • c 0 = 1(调用g(0)需要一定量的工作)
  • c n + 1 = c n + 1(调用g(n)执行一定量的自己的工作,然后调用g(n-1)

我们可以查看几个值来查看我们是否发现了一个模式:

  • c 0 = 1
  • c 1 = c 0 + 1 = 1 + 1 = 2
  • c 2 = c 1 + 1 = 2 + 1 = 3
  • c 3 = c 2 + 1 = 3 + 1 = 4

一般来说,它看起来像c n = n + 1.如果你愿意的话,可以通过归纳证明来形式化这个,但是现在我们要坚信它.这意味着g的运行时间是O(n).

现在,让我们让d n成为调用f(n)的运行时.请注意

  • d 0 = 1(调用f(0)做一定量的工作)
  • d n + 1 = d n + c n + 1(调用f(n + 1)调用g(n + 1),需要c n + 1工作,然后调用f(n)

我们可以扩展它,看看我们是否看到了一种模式.

  • d 0 = 1
  • d 1 = c 1 + d 0 = 2 + 1
  • d 2 = c 2 + d 1 = 3 + 2 + 1
  • d 3 = c 3 + d 2 = 4 + 3 + 2 + 1

通常,它看起来像d n = n +(n-1)+(n-2)+ ... + 1.如果您愿意,可以通过归纳将其形式化.这是一个着名的和,它可以达到n(n + 1)/ 2.这个数量碰巧是Θ(n 2),所以整个运行时间是Θ(n 2).