连续子数组零尾数问题
问题描述
小F正在研究一个数组,并想要计算出其中的连续子数组的某种特性。给定一个整数数组,你需要编写一个函数来返回乘积末尾零的数量大于等于 x 的连续子数组的数量。
由于答案可能非常大,你需要将结果对 10^9 + 7 取模后再返回。
思路
要计算数组中连续子数组的数量,这些子数组的乘积末尾零的数量大于等于 x。末尾零的数量由乘积中因子2和因子5的数量决定,因为每个末尾零对应一对因子2和因子5。
预先储存每个数的因子
对于每个元素计算其包含的2和5的因子数量,分别存储起来。
双指针
使用双指针法来遍历所有可能的子数组。对于每个子数组,计算其因子2和因子5的数量,并判断是否满足条件(即因子2和因子5的最小值大于等于 x)。
时间复杂度:
- 对于每个数组中的元素,我们都需要计算其包含的2和5的因子数量。这一步骤需要遍历整个数组一次,并且对于每个元素,最坏的情况下需要进行次除法操作来计算因子数量(这里
num是数组中的元素)。因此预处理阶段的时间复杂度为,其中n是数组的长度,max_num是数组中最大的元素。 - 在滑动窗口阶段,我们使用两个指针(
left和right)来表示当前窗口的边界。每个指针最多遍历数组一次,因此这个阶段的时间复杂度为O(n)。在窗口内部,我们不断更新2和5的计数器,并在满足条件时更新结果。这些操作都是常数时间操作。
最终时间复杂度为O(n * log(max_num))
空间复杂度:
MOD = 10**9 + 7
def count_factors(n, factor):
"""计算n中包含多少个factor因子"""
count = 0
while n % factor == 0:
n //= factor
count += 1
return count
# 预处理每个数字中的2和5的因子数量
factors = [(count_factors(num, 2), count_factors(num, 5)) for num in a]
left = 0
count_2 = 0
count_5 = 0
result = 0
for right in range(len(factors)):
count_2 += factors[right][0]
count_5 += factors[right][1]
# 当前窗口内的2和5的最小值大于等于x
while min(count_2, count_5) >= x and left <= right:
# 更新结果
result = (result + (len(factors) - right)) % MOD
# 移动左边界
count_2 -= factors[left][0]
count_5 -= factors[left][1]
left += 1
return result