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,这个零不仅不会造成错误解,还是必要的