leetcode 560.和为k的子数组 | 叱诧风云 !前缀和 + 哈希表优化!

. - 力扣(LeetCode)

这道题目的解法我个人认为是非常的巧妙的,因为一开始我是没有想到用前缀和和哈希表来解决,所以今天在这里写一篇题解,来回顾也算是巩固一下我对于这道题目的理解。

首先我先来解释一下,用前缀和的思路是什么样的,我们知道这道题目是让你计算一个连续的子数组,也就是该数组中一连串的元素值的和,判断他们的和是不是等于k,讲到这里,你不是有一些启发呢?

来看一个例子吧,拿题目的例子举例 

nums数组是这样的  【1 ,2  ,3】 前缀和数组 pre 是这样的 【1, 3, 6】;k的值为2

你看如果我们将pre[1] - pre[0] 是不是就等于2,是不是就等于我k的值。而你再仔细想想pre代表的是前缀和,pre[1]是不是就等于pre[0] + nums[1]啊,所以这不就是相当于我找到了一个连续的和为k的子数组了吗,这就是前缀和的意思,那么哈希表优化又是怎么实现的呢

这里我们先来看一个式子 假设 pre[i] - k = pre[j] ,这个式子是不是就代表在数组中i到j之间的元素的和就等于k,也就是说i到j之间的元素是满足我们的条件的,那这里我们每次计算的实际是我们当前的遍历的位置的前缀和 - k,我们是看这个式子的值是不是我这个数组的前缀和,所以这个时候难免就会算出多个前缀和一样的 ,因为数组中的元素有正有负,但是虽然他们的前缀和一样,但是他们所代表的子数组可不一样,所以这里我们就考虑用unordered_map来记录我们遍历过的前缀和,到时候只需要加上对应的val值就可以了,而且这里的前缀和我们只需要用一个数来表示就可以了,不用真的用一个数组来表示,下面来看具体的代码的实现

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        int cnt = 0; int pre = 0;
        unordered_map<int, int> m;
        m.insert(pair<int, int>(0, 1));
        for (int i = 0; i < nums.size(); i++) {
            pre += nums[i];
            auto p = m.find(pre - k);
            if (p != m.end()) {
                cnt += p->second;
            }
            auto q=m.find(pre);
            if(q==m.end()) m.insert(pair<int,int>(pre,1));
            else q->second++;
        }
        return cnt;
    }
};

 cnt就是用计数的,用来返回最后的最终的结果,pre就是用来表示当前位置的所对应的前缀和,因为当前位置的前缀和就等于前面一个位置的前缀和加上当前的元素的值,并且上一个前缀和都记录在map里,当然是unordered_map,这里还需要注意的是一开始要加入零到map里,这就不用多说了,只要那个式子的值在map里能被找到就加上val的值,然后再将当前的前缀和,加入到map里,最后返回计数器cnt即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值