求数组的子数组之后的最大值
刚才看见了一个很有意思的帖子,讲《编程之美》里的一道题目,和相关延伸,觉得不错,就都总结下来吧。
一个有N个整数元素的一维数组(A[0],A[1],...A[n-2],A[n-1]),求这个数组的子数组之和的最大值?
假设已经知道(A[1],...A[n-1])中和最大的一段之和为All[1],并且已经知道(A[1],...A[n-1])中包含A[1]的和最大的一段的和为Start[1]。那么,(A[0],...A[n-1])中问题的解All[0]为max{A[0],A[0]+Start[1],All[1]}
所以,得到程序如下:
1 int MaxSum(int A[], int n)
2 {
3 nStart = A[n-1];
4 nAll = A[n-1];
5 for(i=n-2;i>=0;i--)
6 {
7 if(nStart<0)
8 nStart=0;
9 nStart += A[i];
10 if(nStart>nAll)
11 nAll=nStart;
12 }
13 return nAll;
14 }
2 {
3 nStart = A[n-1];
4 nAll = A[n-1];
5 for(i=n-2;i>=0;i--)
6 {
7 if(nStart<0)
8 nStart=0;
9 nStart += A[i];
10 if(nStart>nAll)
11 nAll=nStart;
12 }
13 return nAll;
14 }
时间复杂度仅为O(n)
现在有人将这个题目变了一下型:
同样有一个N个元素的一维数组,要求出不连续子数组和的最大值,不连续的意思,就是子数组中的任意相邻元素,在原数组都不能相邻。
假设从原数组a第i位开始的最大不连续子数组和为m[ i ],那么它的值有两种可能,一种是当前元素a[ i ]与隔一位上子问题解m[ i+2 ]之和(由不连续性质决定),另一种是不包含当前元素而直接等于前一位上子问题解m[ i+1 ],那么我们可以写出递推公式为:m[ i ] = max(a[ i ] + m[ i+2 ], m[ i+1 ])。
如果m[i+1]不包括a[i+1],则其值相当于m[i+2];所以m[ i ] = max(a[ i ] + m[ i+2 ], m[ i+1 ])无误。
程序如下:
1 int maxsum(int* a, int n)
2 {
3 int m2 = 0;
4 int m1 = a[ n-1 ];
5 for(int i = n - 2; i >= 0; i--)
6 {
7 if(m2 < 0) m2 = 0; //处理最后一位为负数或全为负数的情况
8 int tmp = m1;
9 m1 = max(a[ i ] + m2, m1);
10 m2 = tmp;
11 }
12 return m1;
13 }
2 {
3 int m2 = 0;
4 int m1 = a[ n-1 ];
5 for(int i = n - 2; i >= 0; i--)
6 {
7 if(m2 < 0) m2 = 0; //处理最后一位为负数或全为负数的情况
8 int tmp = m1;
9 m1 = max(a[ i ] + m2, m1);
10 m2 = tmp;
11 }
12 return m1;
13 }
浙公网安备 33010602011771号