此代码的Big-O表示法是什么?

时间:2019-06-16 21:21:53

标签: c++ algorithm big-o

我很难在N ^ 2和NlogN之间确定是大O吗?让我失望的是从k <= j开始的第三个嵌套的for循环。我该如何调和?

int Max_Subsequence_Sum( const int A[], const int N )
{
  int This_Sum = 0, Max_Sum = 0;
  for (int i=0; i<N; i++)
  {
    for (int j=i; j<N; j++)
    {
      This_Sum = 0;
      for (int k=i; k<=j; k++)
      {
        This_Sum += A[k];
      }
      if (This_Sum > Max_Sum)
      {
        Max_Sum = This_Sum;
      }
    }
  }
  return Max_Sum;
}

2 个答案:

答案 0 :(得分:4)

这可以通过估计或分析来完成。查看最里面的循环,第二个循环内有j-i个操作。要获得操作总数,总和为:

(1+N)(2 N + N^2) / 6

使算法为O(N ^ 3)。要估算一下,可以看到有三个循环在某个时刻有O(N)个调用,因此它是O(N ^ 3)。

答案 1 :(得分:2)

让我们首先分析最内层的循环:

for (int k=i; k <= j; k++) {
    This_Sum += A[k];
}

此处计数器ki(包括)迭代到j(包括),因此,这意味着for循环的主体是{{1 }}次。如果我们假设从数组中获取第j-i+1个数字是在固定时间内完成的,则算术运算(递增k,计算kThis_Sum之和,然后将A[k]k进行对接,然后在 O(ji)中运行。

jThis_Sum语句的初始化不重要:

if

实际上,如果我们可以在恒定时间内比较两个数字,并将一个变量设置为在恒定时间内由另一个值保留的值,那么无论条件是否成立,操作数都是固定的。

现在,我们可以看一下中间的循环,并抽象出最内层的循环:

This_Sum = 0;
// ...
if (This_Sum > Max_Sum) {
    Max_Sum = This_Sum;
}

此处for (int j=i; j < N; j++) { // constant number of oprations // j-i+1 operations // constant number of operations } 的范围从ji,因此这意味着操作总数为:

N

此总和等于:

 N
---
\
/     j - i + 1
---
j=i

这是一个arithmetic sum [wiki],它等效于:

                   N
                  ---
                  \
(N-j) * (1 - i) + /   j
                  ---
                  j=i

或者当我们扩展它时:

(N - i + 1) × ((1 - i) + (i+N) / 2) = (N - i + 1) × ((N-i) / 2 + 1)

这意味着我们现在可以专注于外部循环:

i2/2 + 3×N/2 - 3×i/2 + N2/2 - N×i + 1

所以现在我们可以再次使用以下方法计算操作次数:

for (int i=0; i<N; i++) {
    // i2/2 + 3×N/2 - 3×i/2 + N2/2 - N×i + 1
}

我们可以在此处使用Faulhaber's formula [wiki]来求和,并获得:

 N
---
\
/  i2/2 + 3×N/2 - 3×i/2 + N2/2 - N×i + 1
---
i=0

或展开形式:

(N+1)×(N2+5×N+6)/6

这就是 O(n 3 算法。