小明是一个五年级的小学生,今天他刚刚学习了整除,想练习一下自己的掌握情况。他在纸上写了一个长度为 n 的正整数序列,a_0, a_1,..., a_{n - 1},然后想了一个正整数 b,他想知道这个序列有多少个连续子串的和满足能够被 b 整除。你可以帮帮他吗?
这道题用使用前缀和和哈希表来优化算法。
关键步骤:
- 前缀和计算:
prefixSum += sequence.get(i);计算当前前缀和。 - 余数计算:
int remainder = prefixSum % b;计算当前前缀和的余数。 - 余数调整:如果余数为负数,调整为正数
if (remainder < 0) remainder += b;。 - 哈希表查找:
if (remainderCount.containsKey(remainder))检查哈希表中是否存在相同的余数。 - 计数更新:
remainderCount.put(remainder, remainderCount.getOrDefault(remainder, 0) + 1);更新哈希表中余数的计数。
完整代码: import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.ArrayList;
public class Main { public static int solution(int n, int b, List sequence) { // 创建一个哈希表来存储前缀和的余数 Map<Integer, Integer> remainderCount = new HashMap<>(); // 初始化前缀和为0,余数为0的情况 remainderCount.put(0, 1);
int prefixSum = 0;
int count = 0;
for (int i = 0; i < n; i++) {
// 计算当前前缀和
prefixSum += sequence.get(i);
// 计算当前前缀和的余数
int remainder = prefixSum % b;
// 如果余数为负数,调整为正数
if (remainder < 0) {
remainder += b;
}
// 如果哈希表中已经存在相同的余数,说明存在子串和为b的倍数
if (remainderCount.containsKey(remainder)) {
count += remainderCount.get(remainder);
}
// 更新哈希表中余数的计数
remainderCount.put(remainder, remainderCount.getOrDefault(remainder, 0) + 1);
}
return count;
}
public static void main(String[] args) {
// 测试用例
List<Integer> sequence = new ArrayList<>();
sequence.add(1);
sequence.add(2);
sequence.add(3);
System.out.println(solution(3, 3, sequence) == 3);
}
}