【leetcode】560. 和为 K 的子数组

题目:

560. 和为 K 的子数组 - 力扣(LeetCode) (leetcode-cn.com)

 

思路1:前缀和

计算数组的前缀和,presum[i]等于nums[0...i-1]所有数的和,presum[0] = 0;

则nums[j...i-1]的值等于presum[i]减去presum[j];

要保证i和j是不越界的

故我们可以遍历全部的子数组num[j...i],再通过前缀和计算子数组中的值的和有多少等于k的,从而计算得出和为k的子数组数量

代码如下:

class Solution {
    public int subarraySum(int[] nums, int k) {
        //构造前缀和数组
        //preSum 记录 nums[0..i-1] 的累加和
        int[] preSum = new int[nums.length+1];
        preSum[0] = 0;
        for(int i=1;i<preSum.length;i++){
            preSum[i] = preSum[i-1]+nums[i-1]; 
        }
        
        int ans = 0;
        //穷举所有的子数组 nums[j..i-1]= presum[i] - presum[j]
        // 从上看j是要小于i的,小于等于i-1
        // 在保证num[j...i-1]中的i-1和j不越界的情况下,也保证了presum中的i和j不越界,穷举出所有的可能的子数数组
        for(int i=1;i<=nums.length;i++){
            // j是可以等于i-1的
            for(int j=0;j<i;j++){
                if(preSum[i]-preSum[j]==k) ans++;
            }
        }

        return ans;
        
    }
}


思路2: 前缀和+哈希表

优化的思路是:我直接记录下有几个 preSum[j] 和 preSum[i] - k 相等,直接更新结果,就避免了内层的 for 循环。我们可以用哈希表,在记录前缀和的同时记录该前缀和出现的次数。

代码:

class Solution {
    public int subarraySum(int[] nums, int k) {
        //构造前缀和数组
        //preSum 记录 nums[0..i-1] 的累加和
        //构建哈希表:表示当前出现的前缀和出现了几次
        HashMap<Integer,Integer> mp  = new HashMap<>();
        mp.put(0,1);

        int ans = 0,prev = 0;
        //穷举所有的子数组 nums[j..i-1]= presum[i] - presum[j]
        // presum[i] - presum[j] == k,即是要找到j值。且j是小于i的
        for(int i=0;i<nums.length;i++){
            prev += nums[i];
            if(mp.containsKey(prev-k)) ans += mp.get(prev-k);
            mp.put(prev,mp.getOrDefault(prev,0)+1);
        }

        return ans;
        
    }
}

 

posted @ 2022-05-03 11:31  MintMin  阅读(14)  评论(0编辑  收藏  举报