一题算法|和可被 K 整除的子数组

题目

给定一个整数数组 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;
}

扫码关注公众号(搜索公众号:平头哥的技术博文)一起交流学习呗

你可能感兴趣的:(一题算法)