连续的子数组和–java–前缀和+同余定理
思路:
这道题最容易想到的是时间复杂度为O(n ^ 2)的暴力法,但只可以通过92个用例,第93个用例无法通过,现在连打表都无法通过了。
数论学的好的朋友可能会想到求解这道题的关键,即利用同余定理。
同余定理简单解释:
(a - b) % c == 0 等价于 a % c == b % c
知道这个,这道题就变得非常简单了,(arr[j] - arr[i]) % k == 0 就可以转换为 arr[j] % k == arr[i] % k
利用哈希表就可以使用o(n)的时间复杂度完成该题目。
代码实现:
class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
// 求前缀和
int arr[] = new int[nums.length + 1];
arr[0] = 0;
for( var i = 1; i < arr.length; ++i ){
arr[i] = nums[ i - 1 ] + arr[ i - 1 ];
}
// 暴力解法:O(n^2)
// for( var i = 0; i < arr.length; ++i ){
// for( var j = i + 2; j < arr.length; ++j ){
// if( (arr[j] - arr[i]) % k == 0 ){
// return true;
// }
// }
// }
// 同余定理:O(n)
// (arr[j] - arr[i]) % k == 0 可以转换为 arr[j] % k == arr[i] % k
Map<Integer,Integer> map = new HashMap<>();
for( int i = 0; i < arr.length; ++i ){
int remainder = arr[i] % k;
if( map.containsKey(remainder) ){
int num = map.get(remainder);
if( i - num >= 2 ){
return true;
}
}else {
map.put(remainder,i);
}
}
return false;
}
}
作者:mai-jia-jun
链接:https://leetcode-cn.com/problems/continuous-subarray-sum/solution/lian-xu-de-zi-shu-zu-he-by-mai-jia-jun-60yj/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。