您的位置:首页 > 其它

最大子序列和问题

2010-01-08 10:40 507 查看
最大子序列和问题:给定整数A1, A2, ..., An(可能有负数),ΣAk的最大值(为方便起见,如果所有整数均为负数,则最大子序列和为0)。

例:输入-2,11,-4,13,-5,-2时,答案为20(从A2到A4)。

算法1:穷举所有可能,立方运行时间。

1 int MaxSubsequenceSum( const int A[ ], int N )
2 {
3 int ThisSum, MaxSum, i, j, k;
4
5 MaxSum = 0;
6 for( i = 0; i < N; i++ )
7 for( j = i; j < N; j++ )
8 {
9 ThisSum = 0;
for( k = i; k <= j; k++ )
ThisSum += A[ k ];

if( ThisSum > MaxSum )
MaxSum = ThisSum;
}
return MaxSum;
}

算法2: 平方运行时间。

1 int MaxSubsequenceSum( const int A[ ], int N )
2 {
3 int ThisSum, MaxSum, i, j;
4
5 MaxSum = 0;
6 for( i = 0; i < N; i++ )
7 {
8 ThisSum = 0;
9 for( j = i; j < N; j++ )
{
ThisSum += A[ j ];

if( ThisSum > MaxSum )
MaxSum = ThisSum;
}
}
return MaxSum;
}

算法3:分治策略,NlogN运行时间。

1 static int Max3( int A, int B, int C )
2 {
3 return A > B ? A > C ? A : C : B > C ? B : C;
4 }
5
6 static int MaxSubSum( const int A[ ], int Left, int Right )
7 {
8 int MaxLeftSum, MaxRightSum;
9 int MaxLeftBorderSum, MaxRightBorderSum;
int LeftBorderSum, RightBorderSum;
int Center, i;

if( Left == Right ) /* Base case */
if( A[ Left ] > 0 )
return A[ Left ];
else
return 0;

Center = ( Left + Right ) / 2;
MaxLeftSum = MaxSubSum( A, Left, Center );
MaxRightSum = MaxSubSum( A, Center + 1, Right );

MaxLeftBorderSum = 0; LeftBorderSum = 0;
for( i = Center; i >= Left; i-- )
{
LeftBorderSum += A[ i ];
if( LeftBorderSum > MaxLeftBorderSum )
MaxLeftBorderSum = LeftBorderSum;
}

MaxRightBorderSum = 0; RightBorderSum = 0;
for( i = Center + 1; i <= Right; i++ )
{
RightBorderSum += A[ i ];
if( RightBorderSum > MaxRightBorderSum )
MaxRightBorderSum = RightBorderSum;
}

return Max3( MaxLeftSum, MaxRightSum,
MaxLeftBorderSum + MaxRightBorderSum );
}

int MaxSubsequenceSum( const int A[ ], int N )
{
return MaxSubSum( A, 0, N - 1 );
}

算法4:线性运行时间。

1 int MaxSubsequenceSum( const int A[ ], int N )
2 {
3 int ThisSum, MaxSum, j;
4
5 ThisSum = MaxSum = 0;
6 for( j = 0; j < N; j++ )
7 {
8 ThisSum += A[ j ];
9
if( ThisSum > MaxSum )
MaxSum = ThisSum;
else if( ThisSum < 0 )
ThisSum = 0;
}
return MaxSum;
}

算法5:修改算法4增加最大子序列和的子序列起始位置和终止位置。

1 int MaxSubsequenceSum( const int A[], int N, int& x, int& y )
2 {
3 int ThisSum, MaxSum, t, j;
4
5 t = 0;
6 ThisSum = MaxSum = 0;
7 for( j = 0; j < N; j++ )
8 {
9 ThisSum += A[j];
if( ThisSum > MaxSum )
{
MaxSum = ThisSum;
y = j;
}else if( ThisSum < 0 )
{
ThisSum = 0;
t = j + 1;
}
if ( t <= y )
x = t;
}
return MaxSum;
}

int main()
{
int x = 0, y = 0;
int A[] = {4, -3, 5, -2, -1, 2, 6, -12};

int r = MaxSubsequenceSum(A, sizeof(A)/sizeof(A[0]), x, y);
printf("%d, %d, %d\n", r, x+1, y+1);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: