连续子串和的整除-前缀和 | 豆包MarsCode AI刷题

60 阅读2分钟

这道“连续子串和的整除”问题有许多解法,其中利用前缀和的方式是一种简洁高效的解决方案。在深入代码实现之前,我们先理解前缀和的概念、优点以及如何在这类问题中应用。


什么是前缀和?

前缀和是一种用于高效计算数组区间和的技术。 定义:数组的前缀和是从数组起始位置到当前位置的所有元素之和。对于数组 arr,前缀和数组 prefix[i] 表示 arr[0] + arr[1] + ... + arr[i]

举例说明: 对于数组 arr = [1, 2, 3, 4],它的前缀和数组为:

  • prefix[0] = 1
  • prefix[1] = 1 + 2 = 3
  • prefix[2] = 1 + 2 + 3 = 6
  • prefix[3] = 1 + 2 + 3 + 4 = 10

利用前缀和,我们可以高效地计算任何区间 [i, j] 的和:如果 i=0,则区间和直接是 prefix[j]

image.png


前缀和的好处

  1. 高效区间求和 利用前缀和,只需 O(1)O(1)O(1) 时间就可以计算区间和,而不需要重新遍历子数组。这在处理需要频繁计算区间和的问题时尤其有用。
  2. 优化复杂度 传统暴力方法需要枚举每个子数组并计算它的和,复杂度为 O(n2)O(n^2)O(n2)。利用前缀和,我们可以将复杂度降为 O(n)O(n)O(n) 或 O(n⋅k)O(n \cdot k)O(n⋅k)(与具体问题有关)。
  3. 结合哈希表进行快速查询 前缀和与哈希表结合,可以高效解决类似本题中“满足特定条件的子数组数目”问题。通过存储前缀和出现的次数,快速判断某个前缀和是否满足条件。

前缀和在本题中的具体使用

题目需求分析

我们需要统计数组中所有连续子数组的和可以被 bbb 整除的情况数。

问题转换
  1. 前缀和公式转换 假设数组的某个区间和为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

  2. 哈希表辅助统计 根据上述公式,我们只需要记录每个前缀和的余数在数组中的出现次数。当当前前缀和的余数与某个之前前缀和的余数相同时,就说明从那个位置到当前的位置构成的子数组和能被 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));
    }
}
​
​