974.Subarray Sums Divisible by K
===
###### tags: `Medium`,`Array`,`Hash Table`,`Prefix Sum`
[974. Subarray Sums Divisible by K](https://leetcode.com/problems/subarray-sums-divisible-by-k/)
### 題目描述
Given an integer array `nums` and an integer `k`, return *the number of non-empty **subarrays** that have a sum divisible by* `k`.
A **subarray** is a **contiguous** part of an array.
### 範例
**Example 1:**
```
Input: nums = [4,5,0,-2,-3,1], k = 5
Output: 7
Explanation: There are 7 subarrays with a sum divisible by k = 5:
[4, 5, 0, -2, -3, 1], [5], [5, 0], [5, 0, -2, -3], [0], [0, -2, -3], [-2, -3]
```
**Example 2:**
```
Input: nums = [5], k = 9
Output: 0
```
**Constraints**:
* 1 <= `nums.length` <= 3 * 10^4^
* -10^4^ <= `nums[i]` <= 10^4^
* 2 <= `k` <= 10^4^
### 解答
#### C++
```cpp=
class Solution {
public:
int subarraysDivByK(vector<int>& nums, int k) {
vector<int> sums(k, 0);
sums[0]++;
int sum = 0, ans = 0;
for (auto n : nums) {
sum = (sum + n % k + k) % k;
ans += sums[sum];
sums[sum]++;
}
return ans;
}
};
```
> `sums`可以用`unordered_map<int, int>`來取代`vector<int>`
> [name=Yen-Chi Chen][time=Thu, Jan 19, 2023]
##### 思路:
1. 若subarray合法, 即`nums[i:j]`可被`k`整除, 利用prefix sum表示為`(sum[j]-sum[i-1] % k) == 0`, 或者是說`sum[j]-sum[i-1] == k * n`, 左右`%k`化簡後變`sum[j]%k == sum[i-1]%k`, 故`sum[j]%k`出現的次數, 即為array以`j`為結束的index時, 合法array會出現的次數
##### 做法:
1. 做`prefix sum` 及 `%k`掃一遍, 累計`%k`值出現的次數為答案
Time: $O(n)$
Extra Space: $O(k)$
> [name=XD] [time= Jan 19, 2023]
#### Python
```python=
class Solution:
def subarraysDivByK(self, nums: List[int], k: int) -> int:
#若 sum[j]%k == sum[i]%k 則ans+=1
# 4 9 9 7 4 5
#0 4 4 4 2 4 0 prefix sum%k
# 四個4 C(4,2) + 兩個0 C(2,2) = 8 + 1 = 9
acc_n = [0]
buf = 0
for n in nums:
buf += n
acc_n.append( buf%k )
stat = dict()
for n in acc_n:
if n in stat:
stat[n] += 1
else:
stat[n] = 1
import math
ans = 0
#print(stat)
for k,v in stat.items():
ans += int( v*(v-1)/2 )
return ans
```
寫完了才看懂樓上的code XDD 理解力薄弱QQ
> [name=玉山]
#### Javascript
```javascript=
function subarraysDivByK(nums, k) {
const map = new Array(k).fill(0);
let sum = 0;
let count = 0;
map[0] = 1;
for (const num of nums) {
sum += num;
const mod = ((sum % k) + k) % k;
count += map[mod];
map[mod]++;
}
return count;
}
```
> 本來寫得太醜了,參考吉神的答案,醜陋版跟TLE版本放在Discord給大家笑
> [name=Marsgoat] [time= Feb 13, 2023]
### Reference
[回到題目列表](https://hackmd.io/@Marsgoat/leetcode_every_day)