leetcode
leetcode 2151 ~ 2200
最小公倍数为 K 的子数组数目

最小公倍数为 K 的子数组数目

难度:

标签:

题目描述

代码结果

运行时间: 33 ms, 内存: 16.4 MB


/*
题目思路:
1. 使用Java Stream无法直接实现子数组的生成和最小公倍数的计算,因此会转换思路。
2. 先生成所有可能的子数组,然后使用Stream API进行过滤和计数。
3. 对每个子数组,计算其最小公倍数,如果等于k,则计数。
*/

import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class Solution {
    // 计算最大公约数
    private int gcd(int a, int b) {
        while (b != 0) {
            int temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }
    // 计算最小公倍数
    private int lcm(int a, int b) {
        return a * (b / gcd(a, b));
    }
    public int subarrayLCM(int[] nums, int k) {
        List<int[]> subarrays = new ArrayList<>();
        for (int i = 0; i < nums.length; i++) {
            for (int j = i; j < nums.length; j++) {
                int[] subarray = IntStream.range(i, j + 1).map(n -> nums[n]).toArray();
                subarrays.add(subarray);
            }
        }
        return (int) subarrays.stream().filter(subarray -> {
            int currentLCM = subarray[0];
            for (int num : subarray) {
                currentLCM = lcm(currentLCM, num);
            }
            return currentLCM == k;
        }).count();
    }
}

解释

方法:

此题解采用动态维护数组内元素的最小公倍数(LCM)的思路。遍历数组时,只考虑那些能够被k整除的元素,因为如果元素x不能被k整除,则任何包含x的子数组的最小公倍数也不能为k。对于能被k整除的元素,使用一个辅助数组a来存储当前考虑的子数组的元素及其索引。每次遇到一个新元素,计算它与a中已有元素的LCM,并更新a。如果a的第一个元素的LCM等于k,则统计以该元素结尾的符合条件的子数组数量。如果遇到不能被k整除的元素,则重置a数组,重新开始统计。

时间复杂度:

O(n^2)

空间复杂度:

O(n)

代码细节讲解

🦆
如何确保在计算两个数的最小公倍数时算法的效率和正确性?
为了确保计算最小公倍数(LCM)的效率和正确性,可以利用最大公约数(GCD)来进行计算。最小公倍数LCM可以通过公式 LCM(a, b) = |a * b| / GCD(a, b) 来计算。这种方法首先使用辗转相除法(Euclid's algorithm)来找到两个数的最大公约数,然后用两数乘积除以最大公约数得到最小公倍数。这种方法在数学上是精确的,并且在算法实现上也是高效的,因为GCD的计算是对数时间复杂度。
🦆
为什么在遇到不能被k整除的元素时需要重置辅助数组a,并将索引o设置为当前元素的索引?
在遇到不能被k整除的元素时,需要重置辅助数组a,并更新索引o,是因为任何包含这个元素的子数组的最小公倍数都不可能是k。因此,从该元素之后重新开始寻找新的子数组,是必要的。将o设置为当前元素索引,是为了在找到满足条件的子数组时,能够正确计算从上一个不能被k整除的元素之后到当前元素为止的子数组数量。这样可以保证所有可能的子数组都被考虑到,同时避免包含无效元素影响结果的准确性。
🦆
题解中提到当a的第一个元素的LCM等于k时,统计以该元素结尾的符合条件的子数组数量。请问这种方法是否能覆盖所有符合条件的子数组,还是可能会遗漏某些情况?
如果a的第一个元素的LCM恰好等于k,那么从上一个不能被k整除的元素后的位置到当前位置的所有子数组都将是符合条件的。因为这些子数组的LCM将由连续的、可以被k整除的元素组成,且没有其他元素影响这个LCM的值。这种方法理论上能覆盖所有符合条件的子数组,不会遗漏。但这前提是算法必须正确维护LCM的值,且逻辑上没有错误。在实际实现时,需要注意细节处理,以确保每个符合条件的子数组都被正确统计。
🦆
题解中提到删除a数组中的多余元素,具体是如何判断哪些元素是多余的?
在题解中,当添加新元素x到辅助数组a时,会更新每个元素的LCM值。如果在更新过程中,某个元素的LCM值与后来的LCM值相同,则意味着该元素以及之前的所有元素可以被更精简的表示。因此,维持这个最小集合的元素是必要的,其他的元素则被认为是多余的。这样做可以减少之后操作的复杂度,确保数组a只保留最关键的信息,即每个不同LCM值的起始位置。

相关问题