和可被 K 整除的子数组
难度:
标签:
题目描述
代码结果
运行时间: 48 ms, 内存: 19.1 MB
/*
* 思路:
* 1. 使用前缀和数组来计算连续子数组的和。
* 2. 利用 HashMap 来存储当前前缀和 mod k 的余数及其出现次数。
* 3. 如果当前前缀和的 mod k 余数在 HashMap 中已经存在,说明从上一次出现该余数的位置到当前的位置之间的子数组之和可被 k 整除。
* 4. 使用 Java Stream API 遍历数组,更新 HashMap 和结果计数。
*/
import java.util.HashMap;
import java.util.stream.IntStream;
public class Solution {
public int subarraysDivByK(int[] nums, int k) {
HashMap<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int[] count = {0};
int[] prefixSum = {0};
IntStream.of(nums).forEach(num -> {
prefixSum[0] += num;
int mod = (prefixSum[0] % k + k) % k; // 确保 mod 为正值
count[0] += map.getOrDefault(mod, 0);
map.put(mod, map.getOrDefault(mod, 0) + 1);
});
return count[0];
}
}
解释
方法:
此题解采用了前缀和与哈希表的结合思想。首先,遍历数组,计算每个位置的前缀和,并对k取余,得到余数。使用哈希表record记录每个余数出现的次数。由于子数组的和可以表示为两个前缀和的差,如果两个前缀和对k取余相同,那么它们的差也能被k整除。因此,对于每个余数,从对应的次数中选取两个不同的前缀和(即组合数C(n,2)),累加到结果中。
时间复杂度:
O(n)
空间复杂度:
O(k)
代码细节讲解
🦆
在解法中,哈希表的键值对中,键代表什么意义?为什么选择这个作为键?
▷🦆
为什么在哈希表`record`初始化时要设置{0:1},这里的1代表了什么意义?
▷🦆
在哈希表更新`record[m] = record.get(m, 0) + 1`这一步中,为什么选择对已有的值进行累加,而不是直接赋值?
▷🦆
题解中提到的组合数公式`v * (v-1) // 2`是如何得出的,它在这个算法中起什么作用?
▷