Leecode.560 和为k的数组
给定一个整数数组和一个整数 k,你需要找到该数组中和为 k 的连续的子数组的个数。
输入:nums = [1,1,1], k = 2
输出: 2 , [1,1] 与 [1,1] 为两种不同的情况。思路:利用前缀和和哈希表,用哈希表来存储累积和的次数,对于每次总和,在哈希表中查询sum-k的次数,即子序列和为k的连续子数组
class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
unordered_map<int,int>mp;
mp[0]=1;
int sum=0,res=0;
for(auto num:nums){
sum+=num;
res+=mp[sum-k];
mp[sum]++;
}
return res;
}
};
Leecode.974 和可被 K 整除的子数组
给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目
输入:A = [4,5,0,-2,-3,1], K = 5
输出:7
解释:
有 7 个子数组满足其元素之和可被 K = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
思路:哈希表存取前缀和模k的数量,然后排列组合,注意负数的取模
class Solution {
public:
int subarraysDivByK(vector<int>& A, int K) {
unordered_map<int,int>mp;
mp[0]=1;
int sum=0,ans=0;
for(int i=0;i<A.size();i++){
sum=(sum+A[i]%K+K)%K;//负数转化
if(mp.count(sum)) ans+=mp[sum];
mp[sum]++;
}
return ans;
}
};
Leecode.523 连续的子数组和
给定一个包含非负数的数组和一个目标整数 k,编写一个函数来判断该数组是否含有连续的子数组,其大小至少为 2,总和为 k 的倍数,即总和为 n*k,其中 n 也是一个整数。
输入: [23,2,4,6,7], k = 6
输出: True
解释: [2,4] 是一个大小为 2 的子数组,并且和为 6。
思路:用哈希表存sum%k,以及第一次出现sum%k的位置,如存在,且位置差大于1则返回true,注意k=0的情况
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
map<int, int> mp;
mp[0] = -1;
int sum = 0;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
if (k != 0) sum %= k;
if (mp.count(sum)) {
if (i - mp[sum] > 1) return true;
} else {
mp[sum] = i;
}
}
return false;
}
};
Leecode.1248 统计「优美子数组」
给你一个整数数组 nums 和一个整数 k。
如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。
请返回这个数组中「优美子数组」的数目。
输入:nums = [1,1,2,1,1], k = 3
输出:2
解释:包含 3 个奇数的子数组是 [1,1,2,1] 和 [1,2,1,1] 。
思路:统计奇数出现的次数
class Solution {
public:
int numberOfSubarrays(vector<int>& nums, int k) {
int n = nums.size();
vector<int> cnt(n + 1, 0);
int odd = 0, ans = 0;
cnt[0] = 1;
for (int i = 0; i < n; ++i) {
odd += nums[i] & 1;
ans += odd >= k ? cnt[odd - k] : 0;
cnt[odd] += 1;
}
return ans;
}
};