https://leetcode.com/problems/continuous-subarray-sum/
Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to the multiple of k, that is, sums up to n*k where n is also an integer.
Example 1:
Input: [23, 2, 4, 6, 7], k=6 Output: True Explanation: Because [2, 4] is a continuous subarray of size 2 and sums up to 6.Example 2:
Input: [23, 2, 6, 4, 7], k=6 Output: True Explanation: Because [23, 2, 6, 4, 7] is an continuous subarray of size 5 and sums up to 42.Note:
- The length of the array won't exceed 10,000.
- You may assume the sum of all the numbers is in the range of a signed 32-bit integer.
直观法:
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
if(k == 0){
for(int i = 1; i < nums.size(); ++i){
if(nums[i] == nums[i-1]) return true;
}
return false;
}
k = abs(k);
unordered_set<int> S;
for(int cur : nums){
unordered_set<int> tem;
for(int pre : S){
if((pre+cur)%k == 0) return true;
tem.insert((pre+cur)%k);
}
S.swap(tem);
S.insert(cur%k);
}
return false;
}
};
数学方法:
https://leetcode.com/problems/continuous-subarray-sum/discuss/150330/Math-behind-the-solutions
Haven't seen anyone post the math or theory behind the solutions yet, so I'm sharing mine. Let me know if there is any better one.
In short, start with mod =0, then we always do mod = (mod+nums[i])%k, if mod repeats, that means between these two mod = x occurences the sum is multiple of k.
Math: c = a % k, c = b % k, so we have a % k = b % k.
Where a is the mod at i and b is the mod at j and a <= b, i < j, because all nums are non-negative. And c is the mod that repeats.
Suppose b-a=d, then we have b % k = ((a+d) % k)%k = (a%k + d%k)%k
In order to make the equation valid: a % k = (a%k + d%k)%k
d%k has to be 0, so d, the different between b and a, is a multiple of k
Example:
[23, 2, 1, 6, 7] k=9
mod = 5, 7, 8, 5 <-- at here we found it
class Solution {
public:
bool checkSubarraySum(vector<int>& nums, int k) {
int sum=0, lastsum=0;
unordered_set<int> S;
for(int cur : nums){
lastsum = sum;
sum += cur;
if(k) sum %= k;
if(S.find(sum) != S.end()) return true;
S.insert(lastsum);
}
return false;
}
};
注意最一开始会加入一个0,这个零不仅不会造成错误解,还是必要的

博客围绕LeetCode上连续子数组和问题展开,给定非负数组和目标整数k,需判断是否存在长度至少为2的连续子数组和为k的倍数。介绍了直观法和数学方法,数学方法通过取模运算,若模重复则两重复点间和为k的倍数,并给出数学推导和示例。
344

被折叠的 条评论
为什么被折叠?



