325.长度最大的子数组

题目

给定一个整数数组(无序且有正有负)和一个目标值,求这个数组中子数组的和为目标值的子数组的最大长度。

思路

子数组是连续的,s[i]表示从0i位置的累加和,s[j]表示0j位置的累加和,那么从j+1~i位置的累加和为s[j]-s[i],他可以表示任意子数组的累加和,如果这个累加和就是目标值aim,那么找出长度最长的即可。
遍历一遍数组,并求出各个位置的累加和,如在i位置时求得为s[i],在此我们是否可以得到在0-i之间的所有子数组中是否存在累加和为aim的,只需要查询下s[i]-aim 这个值是否在之前计算累加和的过程中出现过。

代码

     /*
     * 给定一个全是正数的数组arr, 和一个整数aim, 求累加和为aim的最大子数组长度
     * 基础:子数组是数组中连续的n个元素
     */
    public static int getMaxLength(int[] arr ,int aim){
        if(arr==null||arr.length==0)
            return 0;
        int sum=0;
        int len=0;
        //sum记录从0到i位置处的连续累加和,哈希表记录以value下标结尾从0开始的累加和key
        HashMap<Integer,Integer> map=new HashMap<Integer, Integer>();
        //sum [0----i]  aim  [j+1-----i] sum-aim [0---j]  要求的数从j+1开始,当j+1=0时,即从开头开始,j=-1;
        //不加任何一个数时,累加和为0,此时下标为-1,就表示还没有添加任何数
        map.put(0, -1);
        for(int i=0;i<arr.length;i++){
            sum+=arr[i];
            if(map.containsKey(sum-aim)){//判断哈希表中现在是否存在sum-aim,如果存在得到他的下标j,那么从j+1到i就是子数组和为aim
                //记录的下标应该为最早出现的j 后面再出现不更新(因为要求最大长度)
                len=Math.max(i-map.get(sum-aim), len);
            }
            //在后续遍历过程中如果出现了相同的sum,不更新
            if(!map.containsKey(sum))//该处的sum值是第一次出现,后面再出现的话不更新(因为要求最大长度)
                map.put(sum, i);
        }
        return len;
    }

如果给定的数组全是正整数,那么这道题也可以用滑动窗口的方法解决。滑动窗口法要求在右界固定的情况下,求最大的左界,即通常用来求满足条件的最短子数组。但是由于数组全是正整数,在右界固定的条件下,如果存在满足条件的左界,那这个左界是唯一的。因此使用滑动窗口法可找到所有和等于aim的子数组,从中找出最长的那个就行。
最开始sum=0,right=0,sum一直加arr[right],直到sum>=aim。当sum大于等于aim时,减去arr[left]。

   int maxSubArrayLen(int aim, int[] arr) {
        if(arr==null||arr.length==0||aim<0)
            return 0;
        int sum=arr[0];
        int len=0;
        int left=0;
        int right=0; //sum 为left -right 之间的数之和
        while(right<arr.length){
            if(sum==aim){
                len=Math.max(len, right-left+1);
                sum-=arr[left++];
            }
            else if(sum<aim){
                right++;
                if(right==arr.length)
                    break;
                sum+=arr[right];
            }
            else {
                sum -= arr[left++];
            }
        }
        return len;
    }

参考:https://blog.csdn.net/yjpeng125/article/details/78992123

原文地址:https://www.cnblogs.com/Frank-Hong/p/14176508.html