题目描述:
标签:数组 哈希表 数学 前缀和
给你一个整数数组
nums
和一个整数k
,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:
- 子数组大小 至少为 2 ,且
- 子数组元素总和为
k
的倍数。如果存在,返回
true
;否则,返回false
。如果存在一个整数
n
,令整数x
符合x = n * k
,则称x
是k
的一个倍数。0
始终视为k
的一个倍数。
代码:
思路分析:
1、数学推理,假设pre[i]代表前i个元素的和,所以[j,i]要满足和谐区间的条件,需要
pre[i] - pre[j-1] = k*(0,1,2,...)
也就是说pre[i] % k取余的值 等于 pre[j-1] % k的值,说明[j,i]区间的和sum是k的倍数。
2、明白以上原理就很好做了,定义一个map来存储前缀和pre及对应的下标。如果当前pre[i]对k取余之后的数在map中存在,则取出之前出现的下标,和当前i比较,看是否子数组长度大于2,如果是则返回true,否则,更新map出现的下标为i。
class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
if(nums.length < 2){
return false;
}
Map<Integer,Integer> map = new HashMap<>();
map.put(0,-1);
int pre = 0;
int count = 0;
for(int i = 0;i < nums.length;i++){
pre += nums[i];
int index = pre % k;
if(map.containsKey(index)){
int prevx = map.get(index);
if(i - prevx >= 2){
return true;
}
}else{
map.put(index,i);
}
}
return false;
}
}