题目理解
我们需要计算数组中连续子数组的数量,这些子数组的乘积末尾零的数量大于等于 x。末尾零的数量取决于乘积中因子 2 和 5 的数量,因为每个 10 都是由一个 2 和一个 5 相乘得到的。
数据结构的选择
我们可以使用两个变量来分别记录当前子数组中因子 2 和 5 的数量。
算法步骤
- 计算因子数量:对于数组中的每个元素,计算其包含的因子
2和5的数量。 - 滑动窗口:使用滑动窗口技术来维护当前子数组中因子
2和5的数量。 - 判断条件:在滑动窗口的过程中,判断当前子数组中因子
2和5的最小数量是否大于等于x。 - 更新结果:如果满足条件,则更新结果,并移动窗口的左边界,直到条件不再满足。
关键点
- 使用滑动窗口技术来动态维护当前子数组的因子数量。
- 在每次移动右边界时,更新因子数量,并判断是否满足条件。
- 如果满足条件,则计算当前右边界到数组末尾的所有可能子数组数量,并更新结果。
代码构思
-
count_trailing_zeros函数:- 该函数用于计算一个数中因子
2和5的数量。 - 逻辑正确,没有问题。
- 该函数用于计算一个数中因子
-
solution函数:- 变量初始化:
count_2和count_5初始化为0,result初始化为0,left初始化为0。 - 滑动窗口:使用
right遍历数组,计算每个元素的因子2和5的数量,并更新count_2和count_5。 - 条件判断:在
while循环中,判断当前子数组中因子2和5的最小数量是否大于等于x。 - 结果更新:如果满足条件,则更新
result,并移动left指针,减少因子数量。
- 变量初始化:
代码展示
def count_trailing_zeros(n):
count_2, count_5 = 0, 0
while n % 2 == 0 and n > 0:
count_2 += 1
n //= 2
while n % 5 == 0 and n > 0:
count_5 += 1
n //= 5
return count_2, count_5
def solution(a: list, x: int) -> int:
MOD = 10**9 + 7
n = len(a)
count_2, count_5 = 0, 0
result = 0
left = 0
for right in range(n):
c2, c5 = count_trailing_zeros(a[right])
count_2 += c2
count_5 += c5
while left <= right and min(count_2, count_5) >= x:
result = (result + (n - right)) % MOD
c2_left, c5_left = count_trailing_zeros(a[left])
count_2 -= c2_left
count_5 -= c5_left
left += 1
return result
-
时间复杂度*:
- 当前实现:
O(n^2) - 优化后实现:
O(n)
- 当前实现:
总结
使用滑动窗口技术来动态维护当前子数组的因子数量,确保在 O(n) 时间内完成计算。