连续子数组零尾数问题
问题描述
小F正在研究一个数组,并想要计算出其中的连续子数组的某种特性。给定一个整数
数组,你需要编写一个函数来返回乘积末尾零的数量大于等于x的连续子数组的数
量。由于答案可能非常大,你需要将结果对 10^9 +7 取模后再返回。
测试样例
样例1:
输入: a=[5,2,3,50,4], x=2
输出: 6
样例2:
输入: a=[10,5,2,1], x=3
输出: 0
样例3:
输入: a=[25,4,8], x=1
输出: 2
问题分析:
我们需要找到所有连续子数组,其乘积末尾的零的数量大于或等于给定值 x,并返回符合条件的子数组的数量。
解题思路1
- 双层循环遍历子数组:通过外层循环遍历每个子数组的起始位置
i,内层循环从i开始遍历所有子数组的结束位置j。每次计算当前子数组的乘积并检查其末尾零的个数。 - 末尾零计算:通过
while num % 10 == 0来计算当前子数组乘积末尾零的个数。每当num能被10整除时,就说明末尾有一个零,将其除去并增加零的计数。 - 时间复杂度:该解法的时间复杂度是
O(n^2 * m),其中n是数组长度,m是子数组乘积中的因数10出现的次数。由于每个元素都可能导致子数组中末尾零的增加,时间复杂度相对较高。
实现步骤
-
初始化变量:
MOD = 10**9 + 7:定义结果需要对10^9 + 7取模,以防结果过大。count = 0:用来记录符合条件(末尾零的数量大于或等于x)的子数组个数。
-
遍历所有子数组:
-
外层
for i in range(len(a)):遍历所有可能的子数组的起始位置i。- 对于每个
i,内层循环for j in range(i, len(a)) 遍历所有以i为起始位置,终止位置在j之间的子数组。 num用来存储当前子数组的乘积,初始值设为1。zero_count用来记录当前子数组乘积末尾零的个数,初始值为0。
- 对于每个
-
-
计算子数组的乘积末尾零:
-
对于每个子数组,我们将其所有元素乘积更新到
num中。 -
每次更新
num后,检查其末尾是否有零(即num % 10 == 0)。- 如果有零,将
num除以10并增加zero_count,直到num不再有末尾零。
- 如果有零,将
-
-
检查是否符合条件:
- 在计算完每个子数组的末尾零数量后,如果
zero_count >= x,则表示该子数组符合条件,count加 1。
- 在计算完每个子数组的末尾零数量后,如果
-
返回结果:
- 最后返回
count % MOD,即符合条件的子数组数量对10^9 + 7取模的结果。
- 最后返回
代码实现
def solution(a: list, x: int) -> int:
MOD = 10**9 + 7
count = 0
# 遍历所有子数组
for i in range(len(a)):
num = 1
zero_count = 0 # 用于存储末尾零的个数
for j in range(i, len(a)):
num *= a[j]
# 计算num的末尾零个数
while num % 10 == 0:
zero_count += 1
num //= 10 # 每次去掉末尾零
# 如果末尾零的个数达到x,增加计数
if zero_count >= x:
count += 1
return count % MOD
解题思路2:
根据豆包的描述,还可以用双指针法,但是我看了半天,没整明白,求大神指点。