繁体   English   中英

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

[英]How would I find the time-complexity of a recursive method in Java?

我无法完全掌握复杂性的概念,我想知道如何在这段代码中为方法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开始。 如果我们让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 )。

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

然后丢弃系数和低阶项。 例如,如果你的结果是0.5n ^ 2 + 0.5n,你会下降0.5n,因为它是一个较低阶项 - 不是平方 - 留下0.5n ^ 2,你会丢弃0.5系数,留下n ^ 2 。 这意味着该函数在O(n ^ 2)时间内运行。

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

由于您已经知道g(k)的运行时间本质上是k ,因此您的最终运行时间是从1到n的总和。 如果你知道你的求和公式,你就会知道它的顺序是O(n 2 )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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