560. 和为 K 的子数组(中)

题目

  • 给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。

示例 1:

输入:nums = [1,1,1], k = 2
输出:2

示例 2:

输入:nums = [1,2,3], k = 3
输出:2

法一、暴力枚举

  • 思路:两层for循环,一层遍历数组,第二层根据第一层的当前元素作为子数组的最后一个元素,往前每一步都求和一直到nums第一个元素
var subarraySum = function(nums, k) {
    let cnt=0
    //遍历nums数组
    for(let start=0;start<nums.length;++start){
        let sum=0//当前子数组和
        //把当前遍历到的元素作为子数组的最后一个元素,往前求和
        for(let end=start;end>=0;end--){
            sum+=nums[end]
            if(sum==k){
                cnt++
            }
        }
    }
    return cnt
};

法二、前缀和 + 哈希表优化

  • 前缀和:当前元素及其之前元素的和,可以用来求子数组和,比如:nums=[3,4,7,2,-3]则pre=[3,7,14,16,13]那么pre[4]-pre[1]=6=nums[2]+nums[3]+nums[4]
  • 思路:求子数组和为k的个数,相当于求pre[i]-pre[j-1]=k的个数,可移项得pre[j-1]=pre[i]-k只需要统计pre[j-1]的个数。统计使用一个哈希表,以pre[i]作键,pre[i]出现的次数作值,最后统计哈希表中pre[j-1](或者pre[i]-k)出现的次数
var subarraySum = function(nums, k) {
    // 创建一个映射,用于存储前缀和及其出现次数
    const mp = new Map();
    // 初始化映射,前缀和为0时的出现次数为1
    mp.set(0, 1);
    // 初始化计数器,记录满足条件的子数组数量
    let count = 0;
    // 初始化前缀和
    let pre = 0;
    // 遍历数组中的每一个元素
    for (const x of nums) {
        // 更新当前的前缀和
        pre += x;
        // 检查当前前缀和减去k的值是否存在于映射中
        // 如果存在,说明找到了对应的子数组
        if (mp.has(pre - k)) {
            // 将找到的子数组数量加到计数器中
            count += mp.get(pre - k);
        }
        // 检查当前前缀和是否已经存在于映射中
        if (mp.has(pre)) {
            // 如果存在,增加当前前缀和的出现次数
            mp.set(pre, mp.get(pre) + 1);
        } else {
            // 如果不存在,初始化当前前缀和的出现次数为1
            mp.set(pre, 1);
        }
    }
    // 返回满足条件的子数组数量
    return count;
};
posted @ 2024-10-29 16:49  Frommoon  阅读(11)  评论(0编辑  收藏  举报