【leetcode100-010】【前缀和+hash】和为 K 的子数组

【题干】

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

子数组是数组中元素的连续非空序列。

【思路】

拿到题第一反应是滑动窗口,写到一半才意识到问题,在没有非负条件的情况下窗口左右边界的移动并不能保证子数组和的减小和增大,滑动窗口失去意义。

从三重循环暴力解(遍历左边界i,遍历右边界j,遍历i到j求和)出发,思考优化方法:

  1. 用前缀和+差分优化重复的求和过程,在O(1)时间获取想要的子数组和。
  2. 考虑到返回的是个数不是位置,用hash map直接统计前缀和的分布。
  3. 由于对每个给定元素进行检验时,都只需要用到其左侧的信息,可以将求和和检验过程放在一次遍历中完成。

优化后的思路如下:

  1. 对每一个元素nums[i]求出其前缀和sum
  2. 任意子数组[i,j]的和为j的sum减去i-1的sum,特别的,当i为0时,补充定义i-1的前缀和0
  3. 用hash map存储当前前缀和出现的次数
  4. 用cnt存储当前和为k的子数组总数
  5. 检查当前已存储的前缀和中,值为sum-k的和出现的次数,aka满足区间和为k的子数组次数,将其加到cnt
  6. 将当前前缀和加入map(或增加次数)

【题解】

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int cnt = 0;
        unordered_map<int, int> map;
        map[0] = 1;
        int sum = 0;
        for (auto num : nums)
        {
            sum += num;
            //检查前缀和中与该sum差距为k的和的数量
            cnt += map[sum - k];
            //将当前sum放入hash中
            ++map[sum];
        }
        return cnt;
    }
};

  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值