找出数组中两段不相交的子数组,使其差值最大
问题描述:
Given an array of integers. Find two disjoint contiguous sub-arrays such that the absolute difference between the sum of two sub-array is maximum.
* The sub-arrays should not overlap.
eg- [2 -1 -2 1 -4 2 8] ans - (-1 -2 1 -4) (2 8), diff = 16
解答:可在线性时间内解决。
思路:
以i为划分点将数组划分为A[1:i]和A[i+1,n]两个部分,统计第一个子数组中的最大子数组值a1和最小子数组值a3,统计第二个子数组中的最大子数组值a4和最小子数组值a2.
那么 abs(a1-a2)以及abs(a3-a4)中最大的值就是划分为i时候的的最大值了。
算法步骤:
首先,从左到右。统计A[1:i]中数值和最大的子数组的数值,用A1[i]来表示。然后从右到左,统计A[j:n]中数值和最小的子数组的数值,用A2[j]来表示。注意此时的i就是划分点
其次,从左到右。统计A[1:i]中数值和最小的子数组的数值,用A3[i]来表示。然后从右到左,统计A[j:n]中数值和最大的子数组的数值,用A4[j]来表示。注意此时的i就是划分点
最后,统计abs( A1[i]-A2[i+1] ) 以及abs( A3[i]-A4[i+1] )中的最大值。那就是我们需要的啦。
时间复杂度说明:
为什么说上述算法是线性的呢?
我们注意到只要能说明“统计A[1:i]中数值和最大的子数组的数值,用A1[i]来表示”这一步是线性时间的,那么整个算法也就是线性的。
下面就来说明一下怎么统计这个。
1: max=0; temp=0;
2: for(int k=1; k<=n; k++)
3: {
4: if(A[k]<=0)
5: {
6: A1[k]=max;
7: temp+=A[k];
8: }
9:
10: else
11: {
12: a1=max+temp+A[k];
13: a2=A[k];
14:
15: if(max<a1)max=a1;
16: if(max<a2)max=a2;
17: temp=0; A1[k]=max;
18: }
19:
20: }
21:
补充:2014-3-18,今天又看了这个问题,感觉应该不是线性的而是O(n*n),为社么了?因为子数组的切分点不止一个啊!
哈哈,有质疑是好的,也怪自己当时没仔细考虑,其实是这样的,我们可以把A[1:i]的结果保存下来,计算A[1:i+1]的时候就可以直接用了!!