个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创前缀和(5)_和为k的子数组
收录于专栏【经典算法练习】
本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌
目录
1. 题目链接 :
2. 题目描述 :
3. 解法(一维前缀和) :
算法思路 :
代码展示 :
结果分析 :
1. 题目链接 :
OJ链接: 和为k的子数组
2. 题目描述 :
给你一个整数数组 nums
和一个整数 k
,请你统计并返回 该数组中和为 k
的子数组的个数 。
子数组是数组中元素的连续非空序列。
示例 1:
输入:nums = [1,1,1], k = 2 输出:2
示例 2:
输入:nums = [1,2,3], k = 3 输出:2
提示:
1 <= nums.length <= 2 * 104
-1000 <= nums[i] <= 1000
-107 <= k <= 107
3. 解法(一维前缀和) :
算法思路 :
设i为数组中的任意位置,用sum[i]表示[0,i]区间内所有元素的和.
想知道有多少个[以i为结尾的和为k的子数组],就要找到有多少个起始位置x1, x2, x3...使得[x, i]区间内的所有元素的和为k.那么[0, x]区间内的和是不是就是sum[i] - k了.于是问题就变成:
找到[0, i - 1]区间内,有多少前缀和等于sum[i] - k的即可
我们不用真的初始化一个前缀和数组,因为我们只关心在i位置之前,有多少个前缀和等于sum[i - k]因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边存下之前每一种前缀和出现的次数.
代码展示 :
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map <int, int> hash;
//sum == k时的情况
hash[0] = 1;
int ret = 0, sum = 0;
for(auto x : nums)
{
sum += x;//计算前缀和
if(hash.count(sum - k)) ret += hash[sum - k];//统计个数
hash[sum]++;
}
return ret;
}
};
以i位置结尾的所有的子数组.在[0,i - 1]区间内,有多少个前缀和等于sum[i] - k
结果分析 :
注意细节问题:
1. 前缀和加入哈希表的时机:
在计算i位置之前,哈希表里面只保存[0, i - 1]位置的前缀和
2. 不用真的创建一个前缀和数组
用一个变量sum来标记前一个位置的前缀和即可
3. 如果整个前缀和等于k:
hash[0] = 1;