leetcode *974. 和可被 K 整除的子數組

【題目】*974. 和可被 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]

提示:
1 <= A.length <= 30000
-10000 <= A[i] <= 10000
2 <= K <= 10000

【解題思路1】暴力法(超時)

子數組爲 i 到 j
java取模特殊性,需要將負數轉化爲整數,如-3模除2是1,但是Java中-3%2 == -1 是不符合取模的運算規則的
也可以使用Math.floorMod(sum, K);

class Solution {
    public int subarraysDivByK(int[] A, int K) {
        int count = 0;
        int len = A.length;
        for (int i = 0; i < len; i++) {
            int sum = 0;
            for (int j = i; j < len; j++) {
                sum += A[j];
                if ((sum % K + K) % K == 0) {
                    count++;
                }
            }
        }
        return count;
    }
}

【解題思路2】前綴和 優化暴力法

前綴和
可以假設一個前綴和數組 pre[ i ],表示到 i 位置位置的前綴和,其實也就是到 i 位置位置的累加和。
可有 pre[ j ] - pre[ i ] 得到 i 到 j 位置子數組的和

符合題目要求的前綴和

  1. 當前前綴和可以mod k,故設定map.put(0,1)
  2. 當前前綴和之前出現過 n 次
    如到 A[ i ] 爲止的前綴和是 n 個,A[ i ] 前面在 j、t 位置共出現過2次一樣的前綴和
    說明 j 到 i,t 到 i 的和都是0,也就是j 到 i,t 到 i 這兩個子數組都是 0 mod k,所以前面出現過幾次一樣的前綴和就count加幾
    將前綴和mod k後的結果存入map,方便查找
    在這裏插入圖片描述
class Solution {
    public int subarraysDivByK(int[] A, int K) {
        int count = 0, sum = 0;
        int len = A.length;
        Map<Integer, Integer> map = new HashMap<>();
        map.put(0, 1); //考慮前綴和本身被 K 整除的情況
        for (int item : A) {
            sum += item; //累加和,也是到當前位置的前綴和
            int modulus = (sum % K + K) % K; //java取模特殊性,當被除數是負數時候取模結果是負數需要糾正
            int same = map.getOrDefault(modulus, 0); //獲取和當前前綴和取模結果一樣的前綴和個數
            count += same;
            map.put(modulus, same + 1);
        }
        return count;
    }
}

【解題思路3】排列組合(未研究)

在這裏插入圖片描述

class Solution {
    public int subarraysDivByK(int[] A, int K) {
        Map<Integer, Integer> record = new HashMap<>();
        record.put(0, 1);
        int sum = 0;
        for (int elem: A) {
            sum += elem;
            // 注意 Java 取模的特殊性,當被除數爲負數時取模結果爲負數,需要糾正
            int modulus = (sum % K + K) % K;
            record.put(modulus, record.getOrDefault(modulus, 0) + 1);
        }

        int ans = 0;
        for (Map.Entry<Integer, Integer> entry: record.entrySet()) {
		    ans += entry.getValue() * (entry.getValue() - 1) / 2;
		}
        return ans;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章