“连续字串和的整除问题”题目要求
一、问题描述
小M是一个五年级的小学生,今天他学习了整除的知识,想通过一些练习来巩固自己的理解。他写下了一个长度为 n 的正整数序列 a_0, a_1, ..., a_{n-1},然后想知道有多少个连续子序列的和能够被一个给定的正整数 b 整除。你能帮小M解决这个问题吗?
例如对于[123, 456, 789],14个符合条件的数为:147 149 158 167 169 248 257 259 268 347 349 358 367 369。
二、测试样例
样例1:
输入:
n = 3,b = 3,sequence = [1, 2, 3]
输出:3
样例2:
输入:
n = 4,b = 5,sequence = [5, 10, 15, 20]
输出:10
样例3:
输入:输入:
n = 5,b = 2,sequence = [1, 2, 3, 4, 5]
输出:6
三、题目解析
3.1代码思路
- 前缀和计算:前缀和数组
prefixSum记录从序列开始到当前位置的和。例如,prefixSum[i]表示a[0] + a[1] + ... + a[i]。我们可以使用哈希表来记录前缀和的余数出现的次数。如果两个前缀和的余数相同,那么它们之间的子序列和可以被b整除。 - 余数计算:对于每个前缀和,利用
int remainder = prefixSum % b;计算其对b的余数,并记录在哈希表中。其中,如果余数为负数,则转变为正数,方便代码实现。 - 统计结果:利用
if (remainder == 0) count++;和count += remainderCount.get(remainder);来统计结果,如果余数为零则计数累加。 - 更新哈希表:可以使用哈希表来记录前缀和的余数出现的次数。如果两个前缀和的余数相同,那么它们之间的子序列和可以被
b整除。此方法通过remainderCount.put(remainder, remainderCount.getOrDefault(remainder, 0) + 1);来实现,
3.2详细代码
import java.util.List;
import java.util.ArrayList; // 添加这一行
public class Main {
public static int solution(int n, int b, List<Integer> sequence) {
// 创建一个哈希表来记录前缀和的余数出现的次数
HashMap<Integer, Integer> remainderCount = new HashMap<>();
// 初始化前缀和为0,余数为0的情况
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;
}
// 如果余数为0,说明从开始到当前位置的子序列和可以被b整除
if (remainder == 0) {
count++;
}
// 如果哈希表中已经存在相同的余数,说明存在一个子序列的和可以被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);
}
}
四、知识总结
本题目主要使用了哈希表来解决问题。使用哈希表在这个问题中是一个非常有效的策略,又如下几点原因:
4.1. 快速查找和插入
哈希表提供了平均时间复杂度为 O(1) 的查找和插入操作。这意味着我们可以快速地检查某个余数是否已经出现过,并且可以快速地更新余数的计数。
4.2. 记录前缀和的余数
我们需要记录每个前缀和的余数,以便在后续的遍历中能够快速判断是否存在一个子序列的和可以被 b 整除。通过哈希表,我们可以轻松地记录每个余数的出现次数。
4.3. 统计子序列的数量
如果两个前缀和的余数相同,那么它们之间的子序列和可以被 b 整除。通过哈希表,我们可以快速统计这些子序列的数量