【问题标题】:Determining complexity for functions (Big O notation)确定函数的复杂性(大 O 表示法)
【发布时间】:2016-02-12 22:11:27
【问题描述】:

我在期中遇到了这个问题,我不确定我的答案是 O(n^2) 我想要有解释的答案,谢谢。

int recursiveFun1(int n)
{  for(i=0;i<n;i+=1) 
      do something;                                                                 
    if (n <= 0)
    return 1;
else
    return 1 + recursiveFun1(n-1);}

【问题讨论】:

  • 不,首先你的方法。 “我想要解释的答案”听起来很粗鲁。注意你的语言。
  • 您的标题显示为“Big O”,但在您的文本中,您使用的是小写“o”。请注意these mean different things,所以请准确。此外,do 是 C++ 中引入循环的关键字。如果你改写do_something() 会更清楚。
  • 令人印象深刻的是,您甚至懒得合理地格式化代码。
  • 答案是 O(n^2)除非do something 中的 something 不是 O(1)。

标签: c++ recursion big-o


【解决方案1】:

首先,我将您的代码另加缩进

int recursiveFun1(int n)
{  
  for(i=0;i<n;i+=1) // this is bounded by O(n)
    do something; // I assume this part is O(1)

  if (n <= 0)
    return 1;
  else
    return 1 + recursiveFun1(n-1);
}

首先要说的是,每次recursiveFun1()被调用O(n)都是因为for而付费。虽然n在每次调用时都会减少,但时间仍以O(n)为界。

第二件事是计算recursiveFun1() 会被调用多少次。显然(对我来说)它将被准确地调用 n + 1 次,直到参数 n 达到零值。

所以时间是n + (n-1) + (n - 2) + ... + 1 + 0,即((n+1)n)/2,即O(n^2)

【讨论】:

    【解决方案2】:

    R(n) 表示输入n 的此递归函数的执行时间。然后,如果n 大于 0,它会执行以下操作:

    • ndo something - 假设“某物”具有恒定的运行时间,它会消耗 c1*n 时间
    • 各种支票和簿记工作-恒定时间c2
    • 计算输入n-1 - 一次。这个的运行时间是R(n-1)(根据定义)

    所以

    R(n) = c1*n + c2 + R(n-1)
    

    这个方程有一个解,即O(n^2)。您可以通过归纳来证明它,或者只是通过猜测a*n^2 + b*n + c 形式的解决方案。

    注意:我假设“做某事”具有恒定的运行时间。这似乎是合理的。但是,如果它不是真的(例如它包含一个递归调用),那么您的复杂性将会更大 - 可能会更大,这取决于“某事”在做什么。

    【讨论】:

    • 这个递归让我想起了一个双重嵌套的for循环,无论如何你可以通过绘制递归树来验证它确实是O(n^2),或者你可以说这个函数做线性工作它被称为 n 次,导致 o(n^2) 。很好的答案,赞成。