LeeCode560和为k的子数组(Java)(前缀和)

题目链接:LeeCode560和为k的子数组
题目描述:在这里插入图片描述
这道题最开始想用滑窗做,但是后来考虑数组里面是有负数的,方向是出错的,首先考虑最笨的放法就是遍历一遍确定左边界,然后向后计算是否有结果等于k的子数组。时间复杂度O(n*n),然后考虑前缀和,算出所有的前缀和例如1 1 1 1 1 k=3,前缀和为1 2 3 4 5 结果等于3的子数组就是 4-1,5-2,3-0三种情况。得出代码:

class Solution {
    
    
    public static int subarraySum(int[] nums, int k) {
    
    
        int[] presum=new int[nums.length];
        presum[0]=nums[0];
        int ans=0;
        //求出前缀和
        for (int i = 1; i < presum.length; i++) {
    
    
            presum[i]=presum[i-1]+nums[i];
        }
        //确定左右边界计算所有能成功的前缀和组合
        for (int i = 0; i < nums.length; i++) {
    
    
            for (int j = i; j < nums.length; j++) {
    
    
                if(presum[j]-presum[i]+nums[i]==k)ans++;
            }
        }
        return ans;
    }
}

之后考虑优化,可以用hashmap存下之前出现过前缀的次数,每次找到一个前缀都判断是否有与之配对的前缀以及个数,故而得出答案

class Solution {
    
    
    public static int subarraySum(int[] nums, int k) {
    
    
        int[] presum=new int[nums.length];
        Map<Integer,Integer> map=new HashMap<>();
        presum[0]=nums[0];
        int ans=0;
        //求出所有前缀和
        for (int i = 1; i < presum.length; i++) {
    
    
            presum[i]=presum[i-1]+nums[i];
        }
        //当nums里面有某个数等于k或者第一次算出k时加一
        map.put(0,1);
        for (int i = 0; i < presum.length; i++) {
    
    
            if(map.containsKey(presum[i]-k)){
    
    
            	//有几个与之配对的前缀就加几
                ans+=map.get(presum[i]-k);
            }
            //维护所有前缀
            map.put(presum[i], map.getOrDefault(presum[i],0)+1);
        }
        return ans;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43590593/article/details/114579956