繁体   English   中英

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

[英]What is the Big-O Notation for this code?

我在选择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;
}

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

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

使算法为O(N ^ 3)。 要进行估算,可以看到有三个循环在某个点上有O(N)个调用,因此它是O(N ^ 3)。

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

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

在这里,计数器ki (包括)迭代到j (包括),因此这意味着for循环的主体执行j-i+1次。 如果我们假设从数组中提取第k个数是在固定时间内完成的,并且进行了算术运算(递增k ,计算This_SumA[k]的总和,并将kj ),则这将在O(ji)

This_Sumif语句的初始化不重要:

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
}

这里j范围是iN ,这意味着操作总数为:

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

该总和等于:

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

这是一个算术和 [wiki] ,它等效于:

(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
}

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

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

我们可以在此处使用Faulhaber公式[wiki]来求解此和,并获得:

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

或扩展形式:

N3/6 + N2 + 11×N/6 + 1

因此,这是O(n 3算法。

暂无
暂无

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

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