零子数组

题目描述:求对于长度为n的数组a,求子数组的和接近0的子数组,要求时间复杂度O(nlogn)。

 算法流程:

申请同样长度的空间sum[0...n-1], sum[i]是a的前i项和。

对sum[0...n-1]排序,然后计算sum相邻元素的差,最小值记为min1。

  min1:在a中任意取两个集合,各自元素的和求差的最小值

  sum[0...n-1]的绝对值最小值记为min2

  min2:a的前k个元素的和的绝对值的最小值

  min1和min2的更小者,即为所求。

  1 #include <iostream>                                                         
  2 #include <algorithm>
  3 #include <math.h>
  4 
  5 using namespace std;
  6 
  7 int FindMinSubArry(const int a[],  int n)
  8 {
  9      int *sum = new int[n];
 10     //求数组a前N项和,并存于sum数组
 11     sum[0] = a[0];
 12     for(int i = 1; i < n; ++i)
 13     {
 14         sum[i] = sum[i - 1] + a[i];
 15     }
 16     int min1 = fabs(sum[0]);
 17     //数组a前N项和的绝对值的最小值min1
 18     for(int i = 1; i < n; ++i)
 19     {
 20         if(fabs(sum[i]) < min1)
 21         {
 22             min1 = fabs(sum[i]);
 23         }
 24     }
 25     sort(sum, sum + n);
 26     //求sum数组相邻元素的差的最小值min2
 27     int min2 = fabs(sum[0] - sum[1]);
 28     for(int i = 2; i < n; ++i)
 29     {
 30         if(fabs(sum[i] - sum[i - 1]) < min2)
 31         {
 32             min2 = fabs(sum[i] - sum[i - 1]);
 33         }
 34     }
35   delete [] sum;   
35 return (min1 > min2 ? min2 : min1); 36 } 37 38 int main(int argc, const char *argv[]) 39 { 40 int a[10] = {31, -41, 59, 26, -53, 58, 97, -93, -23, 84}; 41 int a2[5] = {-5, 2, 2, 3, 2}; 42 int min = FindMinSubArry(a, 10); 43 int min2 = FindMinSubArry(a2, 5); 44 cout << min << endl; 45 cout << min2 << endl; 46 return 0; 47 }

 结果如图:

sum本身的计算和相邻元素差的计算,都是 O(N),sum的排序是O(NlogN),因此,总时间复杂度:O(NlogN) 。

posted @ 2015-04-08 12:12  bigshowxin  阅读(306)  评论(0编辑  收藏  举报