題目:和可被 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
今天也是鬱悶,本來題目挺簡單的,自己瞎改測試用例用來debug廢了好多時,一直報內存泄漏的錯誤,最後發現是控制檯K給該沒了,大意。
題目和560很像,思路是前綴和+同餘定理,用長度爲K的數組記錄即可,需要注意的是前綴和的餘數是負數的時候需要+K,遍歷過程中如果和的餘數爲0直接結果直接+1,其他則加同餘數的前綴和個數,第一版如下
int subarraysDivByK(int* A, int ASize, int K){
int* const cnt=(int*)malloc(sizeof(int)*K);
memset(cnt, 0, sizeof(int)*K);
int i,ans=0,sum=0;
for(i=0;i<ASize;i++){
sum += A[i];
sum = (sum % K + K) % K;
if(sum==0)
ans++;
ans+=cnt[sum];
cnt[sum]++;
}
free(cnt);
return ans;
}
運行結果:
後面進行了改進,把初始時候的cnt[0]置1就沒必要每次判斷和是否爲0了,改進後如下
int subarraysDivByK(int* A, int ASize, int K){
int* const cnt = (int*)malloc(sizeof(int) * K);
memset(cnt, 0, sizeof(int) * K);
int i,ans=0,sum=0;
cnt[0]=1;
for(i=0;i<ASize;i++){
sum += A[i];
sum = (sum % K + K) % K;
ans+=cnt[sum];
cnt[sum]++;
}
free(cnt);
return ans;
}
運行結果:
個人感覺官方題解用HashMap的方式還可以優化,像560一樣如果能用數組表示的情況下用HashMap,雖然時間複雜度都是O(N),時間耗費肯定是會增加的。