连续子数组零尾数问题解析 | 豆包MarsCode AI刷题

56 阅读5分钟

题目解析

问题描述: 给定一个整数数组 a 和一个整数 x,计算乘积末尾零的数量大于等于 x 的连续子数组的数量。由于答案可能非常大,结果需要对 10^9 + 7 取模。

思路

  1. 预处理:计算每个元素的因子 2 和 5 的数量。
  2. 前缀和:使用前缀和数组来快速计算任意子数组的因子 2 和 5 的总和。
  3. 滑动窗口:使用滑动窗口技术,遍历所有可能的子数组,计算每个子数组的因子 2 和 5 的数量,并判断是否满足条件。

图解: 假设输入数组 a = [5, 2, 3, 50, 4]x = 2

  1. 预处理

    • 5 的因子 2 和 5 分别为 0 和 1
    • 2 的因子 2 和 5 分别为 1 和 0
    • 3 的因子 2 和 5 分别为 0 和 0
    • 50 的因子 2 和 5 分别为 1 和 2
    • 4 的因子 2 和 5 分别为 2 和 0
  2. 前缀和

    • prefix_2 = [0, 0, 1, 1, 2, 4]
    • prefix_5 = [0, 1, 1, 1, 3, 3]
  3. 滑动窗口

    • 遍历所有可能的子数组,计算每个子数组的因子 2 和 5 的数量。
    • 例如,子数组 [5, 2, 3] 的因子 2 和 5 分别为 1 和 1,不满足条件。
    • 子数组 [5, 2, 3, 50] 的因子 2 和 5 分别为 2 和 3,满足条件。

代码详解

python

def count_factors(num, factor):
    count = 0
    while num % factor == 0:
        count += 1
        num //= factor
    return count

def solution(a: list, x: int) -> int:
    MOD = 10**9 + 7
    n = len(a)
    
    # 计算每个元素的因子 2 和 5 的数量
    factors_2 = [count_factors(num, 2) for num in a]
    factors_5 = [count_factors(num, 5) for num in a]
    
    # 计算前缀和
    prefix_2 = [0] * (n + 1)
    prefix_5 = [0] * (n + 1)
    for i in range(n):
        prefix_2[i + 1] = prefix_2[i] + factors_2[i]
        prefix_5[i + 1] = prefix_5[i] + factors_5[i]
    
    # 初始化结果
    result = 0
    
    # 滑动窗口
    for left in range(n):
        for right in range(left, n):
            count_2 = prefix_2[right + 1] - prefix_2[left]
            count_5 = prefix_5[right + 1] - prefix_5[left]
            if min(count_2, count_5) >= x:
                result = (result + 1) % MOD
    
    return result

if __name__ == '__main__':
    # 测试用例
    print(solution(a=[5, 2, 3, 50, 4], x=2) == 6)
    print(solution(a=[10, 5, 2, 1], x=3) == 0)
    print(solution(a=[25, 4, 8], x=1) == 2)

知识总结

新知识点

  1. 前缀和:前缀和数组可以快速计算任意子数组的和,适用于需要频繁查询子数组和的场景。
  2. 滑动窗口:滑动窗口技术可以高效地遍历所有可能的子数组,适用于需要检查子数组特性的场景。
  3. 因子计算:通过不断除以因子来计算一个数的因子数量。

理解与建议

  • 前缀和:前缀和数组的构建和使用非常简单,但能显著提高查询效率。建议在遇到需要频繁查询子数组和的题目时优先考虑使用前缀和。
  • 滑动窗口:滑动窗口技术可以避免嵌套循环带来的高时间复杂度,适用于需要检查子数组特性的题目。建议在遇到需要检查子数组特性的题目时优先考虑使用滑动窗口。
  • 因子计算:因子计算是一个基础但重要的操作,可以通过不断除以因子来计算一个数的因子数量。建议在遇到需要计算因子数量的题目时熟练掌握这种方法。

问题总结

可能出现的问题及解决方法

  1. 时间复杂度过高

    • 问题:最初的代码使用了两层嵌套循环来遍历所有可能的子数组,导致时间复杂度过高,无法在合理的时间内处理大规模数据。
    • 解决方法:使用双指针技术,减少不必要的重复计算。通过移动 left 指针,确保每个子数组的因子 2 和 5 的数量满足条件。
  2. 滑动窗口逻辑不严谨

    • 问题:滑动窗口的逻辑不够严谨,没有正确地处理每个子数组的因子 2 和 5 的数量,导致结果不准确。
    • 解决方法:确保在滑动窗口中正确地计算每个子数组的因子 2 和 5 的数量,并在满足条件时正确地计数。
  3. 取模操作不正确

    • 问题:在计算结果时没有正确地对 10^9 + 7 取模,导致结果超出预期范围。
    • 解决方法:在每次更新结果时,立即对 10^9 + 7 取模,确保结果始终在合理范围内。
  4. 边界条件处理不当

    • 问题:在处理边界条件时,可能会遗漏某些特殊情况,导致结果不准确。
    • 解决方法:在编写代码时,仔细检查边界条件,确保所有可能的情况都被正确处理。例如,当数组为空或 x 为 0 时,应返回 0。
  5. 前缀和数组初始化错误

    • 问题:前缀和数组初始化错误,导致后续计算结果不正确。
    • 解决方法:确保前缀和数组的初始化正确,特别是初始值为 0 的部分。例如,prefix_2 = [0] * (n + 1) 和 prefix_5 = [0] * (n + 1)
  6. 因子计算错误

    • 问题:因子计算函数 count_factors 可能存在逻辑错误,导致计算结果不正确。
    • 解决方法:仔细检查 count_factors 函数的逻辑,确保其能够正确计算每个数的因子 2 和 5 的数量。
希望这些内容能帮助你在豆包MarsCode AI刷题过程中更加得心应手,不断提升自己的算法能力和编程水平。