[英]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];
}
在这里,计数器k
从i
(包括)迭代到j
(包括),因此这意味着for
循环的主体执行j-i+1
次。 如果我们假设从数组中提取第k
个数是在固定时间内完成的,并且进行了算术运算(递增k
,计算This_Sum
和A[k]
的总和,并将k
与j
),则这将在O(ji) 。
This_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
}
这里j
范围是i
到N
,这意味着操作总数为:
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.