连续子数组零尾数问题(不会双指针求大佬指点) | 豆包MarsCode AI刷题

66 阅读3分钟

连续子数组零尾数问题

问题描述

小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

  1. 双层循环遍历子数组:通过外层循环遍历每个子数组的起始位置 i​,内层循环从 i​ 开始遍历所有子数组的结束位置 j​。每次计算当前子数组的乘积并检查其末尾零的个数。
  2. 末尾零计算:通过 while num % 10 == 0​ 来计算当前子数组乘积末尾零的个数。每当num​能被 10 整除时,就说明末尾有一个零,将其除去并增加零的计数。
  3. 时间复杂度:该解法的时间复杂度是 O(n^2 * m)​,其中 n​ 是数组长度,m​ 是子数组乘积中的因数 10 出现的次数。由于每个元素都可能导致子数组中末尾零的增加,时间复杂度相对较高。

实现步骤

  1. 初始化变量:

    • ​MOD = 10**9 + 7​:定义结果需要对 10^9 + 7​ 取模,以防结果过大。
    • ​count = 0​:用来记录符合条件(末尾零的数量大于或等于 x​)的子数组个数。
  2. 遍历所有子数组:

    • 外层 for i in range(len(a))​:遍历所有可能的子数组的起始位置 i​

      • 对于每个 i​,内层循环 for j in range(i, len(a))​ 遍历所有以 i​ 为起始位置,终止位置在 j​ 之间的子数组。
      • ​num​ 用来存储当前子数组的乘积,初始值设为 1​
      • ​zero_count​ 用来记录当前子数组乘积末尾零的个数,初始值为 0​
  3. 计算子数组的乘积末尾零:

    • 对于每个子数组,我们将其所有元素乘积更新到 num​ 中。

    • 每次更新 num​ 后,检查其末尾是否有零(即 num % 10 == 0​)。

      • 如果有零,将 num​ 除以10并增加 zero_count​,直到 num​ 不再有末尾零。
  4. 检查是否符合条件:

    • 在计算完每个子数组的末尾零数量后,如果 zero_count >= x​,则表示该子数组符合条件,count​ 加 1。
  5. 返回结果:

    • 最后返回 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:

根据豆包的描述,还可以用双指针法,但是我看了半天,没整明白,求大神指点。