前缀和非常精巧的用key作为一个可重复出现的条件,value为最早出现这个条件值的下标
例题
* 给你一个整数数组 nums 和一个整数k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:
*
* 子数组大小 至少为 2 ,且
* 子数组元素总和为 k 的倍数。
* 如果存在,返回 true ;否则,返回 false 。
*
* 如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。
*
* 输入:nums = [23,2,4,6,7], k = 6
* 输出:true
* 解释:[2,4] 是一个大小为 2 的子数组,并且和为 6 。
*
* 输入:nums = [23,2,6,4,7], k = 6
* 输出:true
* 解释:[23, 2, 6, 4, 7] 是大小为 5 的子数组,并且和为 42 。
* 42 是 6 的倍数,因为 42 = 7 * 6 且 7 是一个整数。
*
* 输入:nums = [23,2,6,4,7], k = 13
* 输出:false
*
* 提示:
*
* 1 <= nums.length <= 105
* 0 <= nums[i] <= 109
* 0 <= sum(nums[i]) <= 2^31 - 1
* 1 <= k <= 2^31 - 1
public static boolean checkSubarraySum(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
int length = nums.length;
int sum[] = new int[length];
sum[0] = nums[0];
for(int i=1;i<length;i++){
sum[i] = nums[i] + sum[i-1];
}
map.put(0,-1);
for(int j=0;j<length;j++){
int remainder = sum[j]%k;
if(map.containsKey(remainder)){
int preIndex = map.get(remainder);
if((j-preIndex)>=2){
return true;
}
}else {
map.put(remainder,j);
}
}
return false;
}
/**
* 给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。
*
* 输入: nums = [0,1]
* 输出: 2
* 说明: [0, 1] 是具有相同数量0和1的最长连续子数组。
*
* 输入: nums = [0,1,0]
* 输出: 2
* 说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
*
* 提示:
*
* 1 <= nums.length <= 105
* nums[i] 不是 0 就是 1
*/
public static int findMaxLength(int[] nums) {
int length = nums.length;
int count = 0;
Map<Integer,Integer> map = new HashMap<>();
map.put(0,-1);
int maxLength = 0;
int preIndex = 0;
int tempLength = 0;
for(int i=0;i<length;i++){
if(nums[i]==1){
count++;
}else {
count--;
}
if(map.containsKey(count)){
preIndex = map.get(count);
tempLength = i-preIndex;
if(tempLength>maxLength){
maxLength = tempLength;
}
}else {
map.put(count,i);
}
}
return maxLength;
/*for(int i=0;i<length;i++){
for(int j=i+1;j<length;j+=2){
int tempLength = j-i+1;
int tempSum = sum[j]-sum[i]+nums[i];
if(tempLength!=0 && tempSum!=0){
if(i!=j && tempLength/tempSum == 2 && tempLength%tempSum==0){
if(tempLength>max){
max = tempLength;
}
}
}
}
}*/
}