算法总结之 未排序数组中累加和小于或等于给定值的最长子数组长度

 给定一个无序数组arr,其中元素可正、可负、可0,给定一个整数k,求arr所有的子数组中累加和小于或等于k的最长子数组长度。

例如: arr=[3,-2,-4,0,6] , k=-2, 相加和小于或者等于-2的最长子数组为{3,-2,-4,0}, 所以结果返回4

 

解题思想(我称之为预处理思想):

   预处理思想,把信息记录下来

   累加和数组的改变

累加和数组中的最大值

用二分查找第一个大于等于某个值的位置

  有序适合用二分查找

 

  首先生成 sumArr  就是累加后的数组   这个数组大哦  因为 第一个为0 表示当没有任何一个数时的累加和为0

  其次 生成sumArr的左侧最大数helpArr,  sumArr={0,1,3,2,7,5}  ->help={0,1,3,3,7,7}   我们只关心大于或等于某一个值的累加和最早出现的位置!

  helpArr是sumArr每个位置上的左侧最大值数组,那么当然是有序的!

 所以可以用二分查找法!查找大于或等于某一个值的累加和最早出现的位置。

 

package TT;

public class Test72 {
  
     public static int maxLength(int[] arr, int k ){
         
         int[] h = new int[arr.length+1];
         
         int sum = 0;
         h[0] = sum;
         
         for(int i =0; i !=arr.length; i++){
             sum +=arr[i];
             h[i+1]=Math.max(sum, h[i]);
         }
         
         sum = 0;
         int res = 0;
         int pre = 0;
         int len = 0;
         
         for(int i =0; i!=arr.length; i++){
             
             sum +=arr[i];
             pre = getLessIndex(h, sum-k);
             len = pre == -1 ? 0 : i-pre+1;
             res = Math.max(res, len);
     
         } 
         return res;          
     }
    
     public static int getLessIndex(int[] arr, int num){
         int low = 0;
         int high = arr.length-1;
         int mid = 0;
         int res=-1;
         while(low <= high){
             mid = (low+high)/2;
             if(arr[mid]>=num){
                 res=mid;
                 high=mid-1;
             }else {
                low = mid +1;
            }     
         }
           
         return res;     
     }
    
     public static void main(String[] args){
         
          int[] arr = new int[5];
          arr[0]=3;
          arr[1]=-2;
          arr[2]=-4;
          arr[3]=0;
          arr[4]=6;

        int x = maxLength(arr,-2);
        System.out.println(x);
          
         
         
     }
     
     
     
}

 

 

posted @ 2017-09-07 15:46  toov5  阅读(873)  评论(0编辑  收藏  举报