1.4 前缀和
1.4.1 连续的子数组和(523)
题目:
给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:
子数组大小 至少为 2 ,且
子数组元素总和为 k 的倍数。
如果存在,返回 true ;否则,返回 false 。
如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 x 是 k 的一个倍数。0 始终视为 k 的一个倍数。
输入:nums = [23,2,4,6,7], k = 6
输出:true
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6 。
思路:
将nums构造成前缀和数组array
array的数组大小 = nums数组大小+1
例如数组nums = [1,2,3,4,5];
array为 [0,1,1+2,1+2+3,1+2+3+4,1+2+3+4+5]
题目要求,子数组大小>=2 子数组元素总和为k的倍数
根据同余定理 b-a为k的倍数
则 b = x1*k+y1 a = x2*k+y2
b-a = (x1-x2)*k+(y1-y2) b-a为k的倍数 则y1 = y2 b和a的模相等
解法
class Solution {
public boolean checkSubarraySum(int[] nums, int k) {
int[] array = new int[nums.length+1];
Set<Integer> set = new HashSet<>();
for(int i = 1;i<=nums.length;i++){
array[i] = array[i-1]+nums[i-1];
}
//同余定理
//b-a 是否为k的倍数 只需知道b和a的模是否相等
//b = x1*k+y1 a = x2*k+y2
//b-a = (x1-x2)*k+(y1-y2) 由于b-a为k的倍数 所以y1=y2
for(int i = 2;i<=nums.length;i++){
//取到每个元素的余数
//例如 原数组 [1,2,3,4,5,6]
//前缀和数组 [0,1,1+2,1+2+3,1+2+3+4,1+2+3+4+5,1+2+3+4+5+6]
//往set中放的值为 前缀和数组下标为[0,4]之间的元素的余数
set.add(array[i-2] % k);
//子数组大小>=2 从i开始循环 比较余数是否相等 进行比较的值为 前缀和数组下标[2,6]之间的元素的余数
//例如k = 3
//执行循环
//array[0] % 3 = 0% 3 = 0 set = [0] array[2]%3 = 3%3 = 0 结果0在set中
//如果array[2]的余数在set中 说明 b和a的模相等 说明b-a是k的倍数
if(set.contains(array[i] % k)){
return true;
}
}
return false;
}
}