leetcode hot100

和为k的子数组

leetcode hot100_第1张图片
本题中,要求连续的和为k的子数组。求子数组的题可以用双指针或者前缀和来做,但这个题中涉及负数,用不了双指针。采用前缀和,前缀和就类似数列中前n项和。
leetcode hot100_第2张图片
在上图中,第一行是数组,第二行是前缀和,要求和为6的连续子数组。可以看到,10-4=6 \16-10=6 \ 22-16=6

也就是说,前缀和-k=已有的前缀和。满足这个式子就证明,存在满足条件的子数组。比如,10-6=4,前缀和中存在4,满足条件,此时子数组为1,2,3。

但这样会导致1,1,1 k=2这种情况漏掉,因为此时只有3-1满足条件,但实际上有两个子数组,所以需要对存储的map集合进行初始化,即map(0,1),初始化加入一个0;
leetcode hot100_第3张图片

这个map key是前缀和,value是其出现的次数,比如10出现了2次,那么其value=2,表示满足条件的情况有2种。(1,2,3)和(1,2,3,0)

public class Solution21 {
    public int subarraySum(int[] nums, int k){
        //记录满足条件的次数
        int count = 0;
        //记录前缀和
        int pre = 0;
        //map用于存储前缀和以及前缀和出现的次数 map(前缀和,前缀和出现的次数)
        Map map = new HashMap<>();
        //map初始化,原因就是可能会漏掉[1,1,1] k=2 其中的一种结果
        map.put(0,1);
        
        for (int i = 0; i < nums.length; i++) {
            //循环遍历获取前缀和
            pre += nums[i];
            //如果存在pre-k,则证明存在子数组和为k
            if (map.containsKey(pre-k)){
                //满足条件的时候需要知道该前缀和出现的次数,即满足条件的子数组的个数
                count += map.get(pre-k);
            }
            //存储前缀和,如果不存在,那么他的出现次数应该是1,即第一次出现,如果之前存在,那么就获取之前的次数加1
            map.put(pre,map.getOrDefault(pre,0)+1);
        }
        return count;
    }
}

本题中需要搞清前缀和的概念,即类比数列中前n项和

你可能感兴趣的:(leetcode,java,算法)