最小公倍数为 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)
代码细节讲解
🦆
如何确保在计算两个数的最小公倍数时算法的效率和正确性?
▷🦆
为什么在遇到不能被k整除的元素时需要重置辅助数组a,并将索引o设置为当前元素的索引?
▷🦆
题解中提到当a的第一个元素的LCM等于k时,统计以该元素结尾的符合条件的子数组数量。请问这种方法是否能覆盖所有符合条件的子数组,还是可能会遗漏某些情况?
▷🦆
题解中提到删除a数组中的多余元素,具体是如何判断哪些元素是多余的?
▷