前缀和与哈希表

91 阅读1分钟

小明是一个五年级的小学生,今天他刚刚学习了整除,想练习一下自己的掌握情况。他在纸上写了一个长度为 n 的正整数序列,a_0, a_1,..., a_{n - 1},然后想了一个正整数 b,他想知道这个序列有多少个连续子串的和满足能够被 b 整除。你可以帮帮他吗? 这道题用使用前缀和和哈希表来优化算法。 关键步骤:

  1. 前缀和计算prefixSum += sequence.get(i); 计算当前前缀和。
  2. 余数计算int remainder = prefixSum % b; 计算当前前缀和的余数。
  3. 余数调整:如果余数为负数,调整为正数 if (remainder < 0) remainder += b;
  4. 哈希表查找if (remainderCount.containsKey(remainder)) 检查哈希表中是否存在相同的余数。
  5. 计数更新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);
}

}