【前缀和】和为 K 的子数组

一、题目描述

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的连续子数组的个数 。

示例:

在这里插入图片描述

二、思路

我记得之前我在一篇文章中说,看见连续子数组,就要立刻想到滑动窗口,现在我收回这句话。

这道题是一道很典型的前缀和问题 —— 那么什么是前缀和问题呢

前缀和问题就是用 sum[i] - sum[j] 快速计算数组 [j ,i] 元素和的问题。详细来说,就是通过预处理计算出以第 0 个元素起始,到第 i 个元素结尾的元素之和,并将其记录为数组 sum,从而实现通过 sum[i] - sum[j] 快速计算 [j ,i] 位置的元素和,这样的问题就是前缀和问题。见下图示例:

在这里插入图片描述

三、代码


对本题而言,其重点在于实现一个转换,即将 ([j , i]元素的和 == k) 转化为 (sum[i] - sum[j] == k) 进而转化为 (sum[i] - k == sum[j] ),从而这道题就变成了找在下标 i 之前的指定的 sum[j] 的数量是多少的问题了。

从而,我们使用一 map 在遍历过程中存储 sum[j] 出现的次数,具体实现代码如下,详情请见注释

    // 和为 k 的子数组数目 —— 前缀和问题
    public int subarraySum(int[] nums, int k) {

        int res = 0;
        if(nums == null || nums.length==0){ // 空数组处理
            return res;
        }
        int len = nums.length;
        if(len == 0){
            return res;
        }
        int[] sum = new int[len];
        sum[0] = nums[0];
        for(int i=1; i<len; i++){ // 预处理,得到所有前缀和值, sum[i] 表示 nums 数组中 [0, i] 元素的和
            sum[i] = sum[i-1] + nums[i];
        }

        // 最精彩的部分 —— ([j , i]元素的和 == k) 可以转化为 (sum[i] - sum[j] == k) 可以转化为 (sum[i] - k == sum[j] )
        // 因此我们只需要找出存在几个这样的 sum[k], 使得 (sum[i] - k == sum[j])
        // 为了统计  sum[j] 的个数,我们使用 HashMap 进行记录 ,其 key 为 sum[j] 的值,value 为值相同的 sum[j] 的个数

        Map<Integer, Integer> map = new HashMap<>();
        map.put(0, 1); // 当前前缀和即等于 k ——  sum[i] - k == 0

        for(int i=0; i<nums.length; i++){
            int temp = sum[i] - k;
            res += map.getOrDefault(temp, 0); // 得到指定 sum[j] 数量
            map.put(sum[i], map.getOrDefault(sum[i], 0) + 1); // 统计在 i 之前相同的 sum[j] 的个数
        }

        return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值