连续子数组零尾数问题 | 豆包MarsCode AI刷题

82 阅读4分钟

问题描述

小F正在研究一个数组,并想要计算出其中的连续子数组的某种特性。给定一个整数数组,你需要编写一个函数来返回乘积末尾零的数量大于等于 x 的连续子数组的数量。

由于答案可能非常大,你需要将结果对 10^9 + 7 取模后再返回。


测试样例

样例1:

输入:a = [5, 2, 3, 50, 4] ,x = 2
输出:6

思路

  1. 计数因子

    对于每个数字,计算其包含的因子 2 和因子 5 的数量。

  2. 滑动窗口

    • 使用双重循环遍历所有可能的子数组。
    • 外层循环确定子数组的起始位置 start
    • 内层循环从 start 开始遍历到数组的末尾,计算当前子数组中因子 2 和因子 5 的数量。
  3. 检查条件

    如果当前子数组中因子 2 和因子 5 的最小值大于等于 x,则该子数组满足条件。

  4. 计数结果

    统计所有满足条件的子数组的数量,并对结果取模 10^9+7。

代码详解

假设输入数组 a = [5, 2, 3, 50, 4]x = 2

第一次外层循环 (start = 0)

  • 初始状态

    • count2 = 0
    • count5 = 0
  • 第一次内层循环 (end = 0)

    • num = 5
    • count2 += countFactors(5, 2) = 0 → count2 = 0
    • count5 += countFactors(5, 5) = 1 → count5 = 1
    • Math.min(0, 1) < 2,不满足条件。
  • 第二次内层循环 (end = 1)

    • num = 2
    • count2 += countFactors(2, 2) = 1 → count2 = 1
    • count5 += countFactors(2, 5) = 0 → count5 = 1
    • Math.min(1, 1) < 2,不满足条件。
  • 第三次内层循环 (end = 2)

    • num = 3
    • count2 += countFactors(3, 2) = 0 → count2 = 1
    • count5 += countFactors(3, 5) = 0 → count5 = 1
    • Math.min(1, 1) < 2,不满足条件。
  • 第四次内层循环 (end = 3)

    • num = 50
    • count2 += countFactors(50, 2) = 1 → count2 = 2
    • count5 += countFactors(50, 5) = 2 → count5 = 3
    • Math.min(2, 3) >= 2,满足条件。
    • count++ → count = 1
  • 第五次内层循环 (end = 4)

    • num = 4
    • count2 += countFactors(4, 2) = 2 → count2 = 4
    • count5 += countFactors(4, 5) = 0 → count5 = 3
    • Math.min(4, 3) >= 2,满足条件。
    • count++ → count = 2

第二次外层循环 (start = 1)

  • 初始状态

    • count2 = 0
    • count5 = 0
  • 第一次内层循环 (end = 1)

    • num = 2
    • count2 += countFactors(2, 2) = 1 → count2 = 1
    • count5 += countFactors(2, 5) = 0 → count5 = 0
    • Math.min(1, 0) < 2,不满足条件。
  • 第二次内层循环 (end = 2)

    • num = 3
    • count2 += countFactors(3, 2) = 0 → count2 = 1
    • count5 += countFactors(3, 5) = 0 → count5 = 0
    • Math.min(1, 0) < 2,不满足条件。
  • 第三次内层循环 (end = 3)

    • num = 50
    • count2 += countFactors(50, 2) = 1 → count2 = 2
    • count5 += countFactors(50, 5) = 2 → count5 = 2
    • Math.min(2, 2) >= 2,满足条件。
    • count++ → count = 3
  • 第四次内层循环 (end = 4)

    • num = 4
    • count2 += countFactors(4, 2) = 2 → count2 = 4
    • count5 += countFactors(4, 5) = 0 → count5 = 2
    • Math.min(4, 2) >= 2,满足条件。
    • count++ → count = 4

第三次外层循环 (start = 2)

  • 初始状态

    • count2 = 0
    • count5 = 0
  • 第一次内层循环 (end = 2)

    • num = 3
    • count2 += countFactors(3, 2) = 0 → count2 = 0
    • count5 += countFactors(3, 5) = 0 → count5 = 0
    • Math.min(0, 0) < 2,不满足条件。
  • 第二次内层循环 (end = 3)

    • num = 50
    • count2 += countFactors(50, 2) = 1 → count2 = 1
    • count5 += countFactors(50, 5) = 2 → count5 = 2
    • Math.min(1, 2) < 2,不满足条件。
  • 第三次内层循环 (end = 4)

    • num = 4
    • count2 += countFactors(4, 2) = 2 → count2 = 3
    • count5 += countFactors(4, 5) = 0 → count5 = 2
    • Math.min(3, 2) >= 2,满足条件。
    • count++ → count = 5

第四次外层循环 (start = 3)

  • 初始状态

    • count2 = 0
    • count5 = 0
  • 第一次内层循环 (end = 3)

    • num = 50
    • count2 += countFactors(50, 2) = 1 → count2 = 1
    • count5 += countFactors(50, 5) = 2 → count5 = 2
    • Math.min(1, 2) < 2,不满足条件。
  • 第二次内层循环 (end = 4)

    • num = 4
    • count2 += countFactors(4, 2) = 2 → count2 = 3
    • count5 += countFactors(4, 5) = 0 → count5 = 2
    • Math.min(3, 2) >= 2,满足条件。
    • count++ → count = 6

第五次外层循环 (start = 4)

  • 初始状态

    • count2 = 0
    • count5 = 0
  • 第一次内层循环 (end = 4)

    • num = 4
    • count2 += countFactors(4, 2) = 2 → count2 = 2
    • count5 += countFactors(4, 5) = 0 → count5 = 0
    • Math.min(2, 0) < 2,不满足条件。

完整代码

public class Main {
    public static int solution(int[] a, int x) {
        final int MOD = 1_000_000_007;
        int count = 0;
        int n = a.length;

        for (int start = 0; start < n; start++) {
            int count2 = 0;
            int count5 = 0;

            for (int end = start; end < n; end++) {
                int num = a[end];
                count2 += countFactors(num, 2);
                count5 += countFactors(num, 5);

                if (Math.min(count2, count5) >= x) {
                    count++;
                    count %= MOD;
                }
            }
        }

        return count;
    }

    private static int countFactors(int num, int factor) {
        int count = 0;
        while (num % factor == 0) {
            num /= factor;
            count++;
        }
        return count;
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[]{5, 2, 3, 50, 4}, 2) == 6); 
        System.out.println(solution(new int[]{10, 5, 2, 1}, 3) == 0); 
        System.out.println(solution(new int[]{25, 4, 8}, 1) == 2); 
    }
}

知识总结

  1. 因子分解

    理解如何通过不断除以某个因子来计算一个数中该因子的数量。

  2. 滑动窗口技术

    掌握使用双层循环来遍历所有可能的子数组,并在遍历时动态更新子数组的状态。

  3. 数学性质

    明确乘积末尾零的数量由因子 2 和因子 5 中的较小值决定。