算法练习——和最接近于零的子数组
Posted 大黄奔跑
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法练习——和最接近于零的子数组相关的知识,希望对你有一定的参考价值。
问题描述:
求对于长度为N的数组A,求子数组的和接近0的子数组,要求时间复杂度O(NlogN)
(1) 求出所有的sum[i] sum[i]表示A的前 i 项和
(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 的子数组