和为K的子数组LeetCode560

39 篇文章 0 订阅
13 篇文章 0 订阅
本文介绍了如何使用滑动窗口、暴力求解和前缀和+hash优化的方法解决数组中和等于特定值的子数组数量问题。针对数据可能为负数的情况,详细解析了动态规划和暴力求解的思路,并重点阐述了前缀和与hash_map结合的优化策略,确保算法在处理大规模数据时的效率。此外,还强调了初始化前缀和的重要性,以避免丢失特殊情况的解。
摘要由CSDN通过智能技术生成

目录

题目描述

思路 

思路一--滑动窗口 

思路二--暴力求解 

 思路三--前缀和+hash优化

补充


题目描述

思路 

思路一--滑动窗口 

本来看到题目想着,我的天啊,这不是可以用滑动窗口完美解决吗?直到我看到数据可以为负数,我才开始意识到问题的严重性,最后想着使用动态规划,但是推导了半天硬是推导不出来表达式,无奈选择了暴力求解...

思路二--暴力求解 

思路还是滑动窗口,但是这回遍历时右指针right一直要从左往右遍历到尽头才行,结果也不用说了,超时......


    int subarraySum(vector<int>& nums, int k) {
        int right = -1;
        int ans = 0;
        int count;
        int size = nums.size();
        for (int i = 0; i < size; ++i) {
            count = nums[i];
            right = i;
            while (right < size) {
                ++right;
                count += nums[right];
            }
            if (count == k) ans++;
        }
        return ans;
    }         //这道题因为数据可以是负数,所以说滑动窗口根本就解不出来!!!

 思路三--前缀和+hash优化

  我们来想一想为何时间复杂度这么高?!可以理解,对于每一个确定的i,我们的右指针都要从左到右遍历一遍,我们不妨换一种思路--

我们对于前缀和(从[0,i]这些元素之和),如果两个前缀和相减差为K,那么说明存在一组可行解.我们对于pre[i]来说,只要找到能使得pre[j]+K=pre[i]成立的数量即可,我们每一次更新pre[i]时,其实只要得到pre[i]-K的数量,也就得到了可行解的数量(我们可以使用hash_map).同样的我们为了缩短查找时间,考虑使用hash_map,key存储pre[i]-k,value存储前缀和为pre[i]的数量.

对这里不太理解的同学不妨看一下原题解的动画会清楚很多!

https://leetcode-cn.com/problems/subarray-sum-equals-k/solution/

 

代码如下:


    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> m;
        int pre = 0;
        int ans = 0;
        m.insert({ 0,1 });          //需要注意这里需要加入这一元素,比如1,2,3查找3,一减,键值为0.
        for (auto& num: nums) {
            pre += num;
            if (m.find(pre - k) != m.end()) ans+=m[pre-k];
            m[pre]++;
        }
        return ans;
    }

补充

这里补充一点原题解中没有说的地方,我们需要初始化存储m.insert({0,1}),因为我们对于那些nums[i]==K的值(eg:3,1,1,2,4,5       .K=3) ,我们不能遗漏第一个数值三,对于这种情况,对于第一次出现pre==K的情况,我们需要进行初始化处理!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shallow_Carl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值