题目解析
问题描述: 给定一个整数数组 a 和一个整数 x,计算乘积末尾零的数量大于等于 x 的连续子数组的数量。由于答案可能非常大,结果需要对 10^9 + 7 取模。
思路:
- 预处理:计算每个元素的因子
2和5的数量。 - 前缀和:使用前缀和数组来快速计算任意子数组的因子
2和5的总和。 - 滑动窗口:使用滑动窗口技术,遍历所有可能的子数组,计算每个子数组的因子
2和5的数量,并判断是否满足条件。
图解: 假设输入数组 a = [5, 2, 3, 50, 4] 和 x = 2。
-
预处理:
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。
-
前缀和:
prefix_2 = [0, 0, 1, 1, 2, 4]prefix_5 = [0, 1, 1, 1, 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)
知识总结
新知识点:
- 前缀和:前缀和数组可以快速计算任意子数组的和,适用于需要频繁查询子数组和的场景。
- 滑动窗口:滑动窗口技术可以高效地遍历所有可能的子数组,适用于需要检查子数组特性的场景。
- 因子计算:通过不断除以因子来计算一个数的因子数量。
理解与建议:
- 前缀和:前缀和数组的构建和使用非常简单,但能显著提高查询效率。建议在遇到需要频繁查询子数组和的题目时优先考虑使用前缀和。
- 滑动窗口:滑动窗口技术可以避免嵌套循环带来的高时间复杂度,适用于需要检查子数组特性的题目。建议在遇到需要检查子数组特性的题目时优先考虑使用滑动窗口。
- 因子计算:因子计算是一个基础但重要的操作,可以通过不断除以因子来计算一个数的因子数量。建议在遇到需要计算因子数量的题目时熟练掌握这种方法。
问题总结
可能出现的问题及解决方法:
-
时间复杂度过高:
- 问题:最初的代码使用了两层嵌套循环来遍历所有可能的子数组,导致时间复杂度过高,无法在合理的时间内处理大规模数据。
- 解决方法:使用双指针技术,减少不必要的重复计算。通过移动
left指针,确保每个子数组的因子2和5的数量满足条件。
-
滑动窗口逻辑不严谨:
- 问题:滑动窗口的逻辑不够严谨,没有正确地处理每个子数组的因子
2和5的数量,导致结果不准确。 - 解决方法:确保在滑动窗口中正确地计算每个子数组的因子
2和5的数量,并在满足条件时正确地计数。
- 问题:滑动窗口的逻辑不够严谨,没有正确地处理每个子数组的因子
-
取模操作不正确:
- 问题:在计算结果时没有正确地对
10^9 + 7取模,导致结果超出预期范围。 - 解决方法:在每次更新结果时,立即对
10^9 + 7取模,确保结果始终在合理范围内。
- 问题:在计算结果时没有正确地对
-
边界条件处理不当:
- 问题:在处理边界条件时,可能会遗漏某些特殊情况,导致结果不准确。
- 解决方法:在编写代码时,仔细检查边界条件,确保所有可能的情况都被正确处理。例如,当数组为空或
x为 0 时,应返回 0。
-
前缀和数组初始化错误:
- 问题:前缀和数组初始化错误,导致后续计算结果不正确。
- 解决方法:确保前缀和数组的初始化正确,特别是初始值为 0 的部分。例如,
prefix_2 = [0] * (n + 1)和prefix_5 = [0] * (n + 1)。
-
因子计算错误:
- 问题:因子计算函数
count_factors可能存在逻辑错误,导致计算结果不正确。 - 解决方法:仔细检查
count_factors函数的逻辑,确保其能够正确计算每个数的因子2和5的数量。
- 问题:因子计算函数