LeetCode 560. 和为K的子数组

https://leetcode-cn.com/problems/subarray-sum-equals-k/

这个题第一眼看以为是滑动窗口,直接用滑动窗口做被坑了,负数一出现就人没了。。。

后来直接暴力解,结果被 [0,0,0,0,0,0,0,0,0,0] 0 这个测试用例上了一堂课,乖乖把优化步骤去掉,才能勉强AC

class Solution {
    public int subarraySum(int[] nums, int k) {
        if (nums.length == 0) {
            return 0;
        }
        int res = 0;
        for(int i = 0; i < nums.length; i++){
            int count = 0;
            for(int j = i; j >= 0; j--){
                count += nums[j];
                if(count == k){
                    res++;
                }
            }
        }
        return res;
    }
}

暴力解O(n^2),效率很差,LeetCode给出的反馈如下

执行用时:387 ms
内存消耗:41 MB
 
后来看了评论区和提示,才明白tag中的哈希表是拿来干嘛用的,其实就是统计从0开始到i出现过的sum的次数,然后通过sum-k看看是否存在一个sum-k子数组,使得sum-k + k = sum。就像提示4里面所说的那样。
sum(i,j)=sum(0,j)-sum(0,i), where sum(i,j) represents the sum of all the elements from index i to j-1. Can we use this property to optimize it.
class Solution {
    public int subarraySum(int[] nums, int k) {
        int res = 0;
        HashMap<Integer, Integer> map = new HashMap<>();
        int sum = 0;
        map.put(0,1);
        for(int i = 0; i < nums.length; i++){
            sum += nums[i];
            //其实k可以看成是一个连续的子数组构成的和,根据提示4,我们可以看从0到i的总和减去k这个子数组所代表的和的差是否出现在map中,如果出现就代表存在一个子数组,使得这个子数组加上k可以到达当前的数组,那么我们的结果就要加上这个子数组出现的次数。
            if(map.containsKey(sum - k)){
                res += map.get(sum-k);
            }
            map.put(sum,map.getOrDefault(sum,0)+1);
        }
        return res;
    }
}
原文地址:https://www.cnblogs.com/ZJPaang/p/12893528.html