找出数组中两段不相交的子数组,使其差值最大

问题描述:

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]的时候就可以直接用了!!

你可能感兴趣的:(数组)