这道“连续子串和的整除”问题有许多解法,其中利用前缀和的方式是一种简洁高效的解决方案。在深入代码实现之前,我们先理解前缀和的概念、优点以及如何在这类问题中应用。
什么是前缀和?
前缀和是一种用于高效计算数组区间和的技术。 定义:数组的前缀和是从数组起始位置到当前位置的所有元素之和。对于数组 arr,前缀和数组 prefix[i] 表示 arr[0] + arr[1] + ... + arr[i]。
举例说明: 对于数组 arr = [1, 2, 3, 4],它的前缀和数组为:
prefix[0] = 1prefix[1] = 1 + 2 = 3prefix[2] = 1 + 2 + 3 = 6prefix[3] = 1 + 2 + 3 + 4 = 10
利用前缀和,我们可以高效地计算任何区间 [i, j] 的和:如果 i=0,则区间和直接是 prefix[j]。
前缀和的好处
- 高效区间求和 利用前缀和,只需 O(1)O(1)O(1) 时间就可以计算区间和,而不需要重新遍历子数组。这在处理需要频繁计算区间和的问题时尤其有用。
- 优化复杂度 传统暴力方法需要枚举每个子数组并计算它的和,复杂度为 O(n2)O(n^2)O(n2)。利用前缀和,我们可以将复杂度降为 O(n)O(n)O(n) 或 O(n⋅k)O(n \cdot k)O(n⋅k)(与具体问题有关)。
- 结合哈希表进行快速查询 前缀和与哈希表结合,可以高效解决类似本题中“满足特定条件的子数组数目”问题。通过存储前缀和出现的次数,快速判断某个前缀和是否满足条件。
前缀和在本题中的具体使用
题目需求分析
我们需要统计数组中所有连续子数组的和可以被 bbb 整除的情况数。
问题转换
-
前缀和公式转换 假设数组的某个区间和为sum[i,j],则:sum[i,j] = prefix[j]-prefix[i-1]
如果 sum[i,j]能被 b 整除,则有:
(prefix[j]-prefix[i-1])%b=0
即:
prefix[j]%b=prefix[i−1]%b
-
哈希表辅助统计 根据上述公式,我们只需要记录每个前缀和的余数在数组中的出现次数。当当前前缀和的余数与某个之前前缀和的余数相同时,就说明从那个位置到当前的位置构成的子数组和能被 bbb 整除。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class Main {
public static int solution(int n, int b, List<Integer> sequence) {
// Please write your code here
//用前缀和写一次
int out = 0;
HashMap<Integer,Integer> map = new HashMap<>();
map.put(0,1);
int temp = 0;
for (int i = 0; i < n; i++) {
temp+= sequence.get(i);
for (Integer integer : map.keySet()) {
if((temp-integer)%b==0){
out+=map.getOrDefault(integer, 0);
}
}
map.put(temp, map.getOrDefault(temp, 0)+1);
}
return out;
}
public static void main(String[] args) {
// You can add more test cases here
List<Integer> sequence = new ArrayList<>();
sequence.add(1);
sequence.add(2);
sequence.add(3);
System.out.println(solution(3, 3, sequence));
}
}