算法:管窥算法-零子数组

1.可以用类似  的算法做。

2.一般做法。https://blog.csdn.net/xueyingxue001/article/details/52935547

(注:任何关于子序列的和的都可以用这种思想)

  1.计算出前i项和,sum[i],

  2.因为“数组A第i到j项的和 = 数组前j项的和sum(j) - 数组前i项的和sum(i-1)”(所以有了前i项我数组sum[],就可以得到A数组的所有子序列了,A的子序列不是sum中的元素就是sum中的任意两个元素相减)

         3.所以只需要:把所有子序列一分为二,其中一部分为sum中包含的元素记做 T1集合,另一部分为sum中任意两元素相减的集合记做T2集合。

                   1,定义S[-1] = 0,对sum[-1, 0,..., N-1]排序后计算相邻元素的差的绝对值(排过序之后,相邻元素的差一定比不相邻的小,所以T2集合中的其他元素是不需要计算和比较了的),记做m1。

      2.找出T1集合(即sum)中的元素的绝对值最小的值,记做m2.

      3.比较m1和m2,哪个小就是哪个了。

 1 /**
 2  * 零子算法-要求时间复杂度为nlogn
 3  * @param a
 4  * @return
 5  */
 6     public static int T(int[] a){
 7         //创建sum数组,第i项为a数组的前i项和
 8         List<Integer> sum=new ArrayList<>(a.length);
 9         sum.add(a[0]);
10         for(int i=1;i<a.length;i++){
11             sum.add(sum.get(i-1)+a[i]);
12         }
13 //        对sum排序
14         sum.sort(null);
15         //sum中绝对值最小的为m1,sum相邻元素相减绝对值最小的为m2.
16         int m1=Math.abs(sum.get(0));
17         int m2=Math.abs(sum.get(1)-sum.get(0));
18         int j=0,k=0;
19         for(int i=1;i<sum.size();i++){
20             j=Math.abs(sum.get(i));
21             k=Math.abs(sum.get(i)-sum.get(i-1));
22             if(j<m1){
23                 m1=j;
24             }
25             if(k<m2){
26                 m2=k;
27             }
28         }
29         return m1<m2?m1:m2;
30     }

猜你喜欢

转载自www.cnblogs.com/minconding/p/10453847.html
今日推荐