1. 题目来源
链接:523. 连续的子数组和
2. 题目解析
区间和问题,很明显使用前缀和进行优化。
答案满足 (s[j]-s[i])%k=0
,则等价于 (s[j]%k-s[i]%k)%k=0
,即 s[j]%k==s[i]%k
。
故,针对每一个前缀和终点 s[j]
,仅需判断它之前有没有与它模 k
余数,即 s[j]%k
相同的起点 s[i]%k
存在即可。
枚举顺序:
- 本题要求长度至少为 2,前缀和下标从 1 开始,终点
j
从 2 开始循环,每次将s[j-2]
插入进哈希表,j-2
可能与j
构成一个长度为 2 的答案,且算每一个终点j
的时候,可能构成的答案均已经加入进哈希表了。
在此之前,需要注意 k
值不可为 0,若 k
为 0,则需要判断是否至少存在一个长度为 2 的全 0 子数组。
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
int n = nums.size();
if (!k) {
for (int i = 1; i < n; i ++ )
if (!nums[i - 1] && !nums[i])
return true;
return false;
}
vector<int> s(n + 1);
for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + nums[i - 1];
unordered_set<int> S;
for (int i = 2; i <= n; i ++ ) {
S.insert(s[i - 2] % k);
if (S.count(s[i] % k)) return true;
}
return false;
}
};