题目
给定一个整数数组 A,返回其中元素之和可被 K 整除的(连续、非空)子数组的数目
示例
输入 :A = [4,5,0,-2,-3,1], K = 5
输出:7
解释:
有 7 个子数组满足其元素之和可被 K = 5 整除:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
解题思路
暴力解法
利用双循环将所有可能的连续子数组枚举出来,求出子数组的和
sum
,如sum
可以整除K,则解法数+1。
同余定理
定于一个默认为零的余数
mod
,遍历数组,余数mod
与数组的值求和除于K得出新的余数余数mod
,每出现一次余数mod
,则remainder[mod]
的值+1,因为余数每出现一次说明存在一个解。
实现代码
暴力解法
/**
* 暴力解法,枚举所有连续数组的结果
* @param A
* @param K
*/
public static int forSolution(int[] A, int K) {
int res = 0;
for (int i = 0; i < A.length; i++) {
int sum = A[i];
if (sum % K == 0) ++res;
for (int j = i + 1; j < A.length; j++) {
sum += A[j];
// 被K整除
if (sum % K == 0) ++res;
}
}
return res;
}
同余定理
/**
* 同余定理
* @param A
* @param K
* @return
*/
public static int remainder(int[] A, int K) {
// 新new 一个余数大小的数组
int[] remainder = new int[K];
// 默认有一个解
remainder[0] = 1;
// 余数
int mod = 0;
// 求解个数
int res = 0;
for (int n: A) {
mod = (mod + n) % K;
// 如果余数为负数 我们将余数转为正余数
if (mod < 0) mod += K;
res += remainder[mod];
remainder[mod]++;
}
return res;
}
扫码关注公众号(搜索公众号:平头哥的技术博文)一起交流学习呗