算法练习——和最接近于零的子数组

Posted 大黄奔跑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法练习——和最接近于零的子数组相关的知识,希望对你有一定的参考价值。

问题描述:

求对于长度为N的数组A,求子数组的和接0的子数组,要求时间复杂度O(NlogN) 

(1) 求出所有的sum[i]  sum[i]表示A的前 项和
(2) 对sum[-1,0,...,N-1]排序,然后计算sum相邻元素的差的绝对值,最小记为 min1   
(3) min1 : 在A中任意取两个相邻子数组的和,求两者差的最小值。(相当于 i——j和的最小值)
(4) min2 : A的前k个元素的和的绝对值的最小值(为sum[0,1....n-1]中的最小值)
(5) min1和min2更小者,即为所求。

 

 1 public class SumIsZero {
 2     public static int SumMinIsZero(int[] a, int length){
 3         int[] sum = new int[length];
 4         //同时定义sum[-1] = 0;
 5         //sum[-1] = 0;
 6         //求前n项的和并且存在sum数组中,在从里面求出绝对值最小的数
 7         sum[0] = a[0];
 8         int i;
 9         //求出所以的sum[i]
10         for (i = 1; i < length; i++) {
11             sum[i] = sum[i-1]+a[i];
12         }
13         int min2 = Math.abs(sum[0]);
14         for (i = 0; i < sum.length; i++) {
15             if (Math.abs(sum[i]) < min2) 
16                 min2 = Math.abs(sum[i]);
17         }
18         
19         //同时对数组sum做排序
20         quickSort(sum, 0, length-1);
21         
22         //求sum排序之后的相邻元素的最小值min1
23         int min1 = Math.abs(sum[0]-sum[1]);
24         for (int j = 2; j < sum.length; j++) {
25             if (Math.abs(sum[j] - sum[j-1]) <min1) 
26                 min1 = Math.abs(sum[j] - sum[j-1]);
27         }
28         return (min1 > min2 ? min2:min1);
29     }

 

快速查找(保证满足题目的时间复杂度)

 1 public static void quickSort(int[] a, int low,int high){
 2         int i,j;
 3         int temp;
 4         
 5         i=low;
 6         j=high;
 7         temp=a[low];                //取第一个元素为标准数据元素
 8         //下面的对左边和右边的扫描定位反复进行,直到左边的下标i大于或者等于右边元素的下标为止
 9         while(i<j){
10             //在数组的右边扫描,如果数大于哨兵,则不改变位置,否则将j上的元素马上移动到i位置,
11             //并且马上扫描左边
12             while( i < j&& a[j]>=temp) j--;
13             if (i<j) {
14                 a[i]=a[j];
15                 i++;
16             }
17             
18             //在数组的左边扫描,如果数小于哨兵,则不改变位置,否则将左边i处的位置交换到
19             //右边j处的位置,并且转回扫描右边
20             while( i < j&& a[i] < temp) i++;
21             if (i<j) {
22                 a[j]=a[i];
23                 j--;
24             }
25         }
26         
27         a[i]=temp;
28         
29         //对左边的子集合做递归查询
30         if (low<i) {
31             quickSort(a, low, i-1);
32         }
33         //对右边的子集合做递归查询
34         if (i<high) {
35             quickSort(a, j+1, high);
36         }
37     }

 

 

但是以上算法只是简单的得到了最接近零的子数组的和,并没有得到所有的子数组。

 

以上是关于算法练习——和最接近于零的子数组的主要内容,如果未能解决你的问题,请参考以下文章

如何在 O(nlogn) 中找到总和最接近零或某个值 t 的子数组

(MNIST - GAN) 鉴别器和生成器误差在第一次迭代后接近于零

二分查找算法应用总结

零和数组

对于非常接近零的值,双重计算运行速度要慢得多

和最接近0的两个数