[每日一题]1819.序列中不同最大公约数的数目
1819. 序列中不同最大公约数的数目 给你一个由正整数组成的数组 nums 。数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。
例如,序列 [4,6,16] 的最大公约数是 2 。
数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。
例如,[2,5,10] 是 [1,2,1,2,4,1,5,10] 的一个子序列。
计算并返回 nums 的所有 非空 子序列中 不同 最大公约数的 数目 。
举例:
-
输入:nums = [6,10,3] 输出:5 解释:上图显示了所有的非空子序列与各自的最大公约数。 不同的最大公约数为 6 、10 、3 、2 和 1 。
-
输入:nums = [5,15,40,5,6] 输出:7
Solution
class Solution {
public int countDifferentSubsequenceGCDs(int[] nums) {
// 求出当前数组的最大值
int maxVal = Arrays.stream(nums).max().getAsInt();
// 定义一个长度为 maxVal + 1 的数组
boolean[] occured = new boolean[maxVal + 1];
// 用 true 表示 occured 中对应下标的数在 nums 中存在
for (int num : nums) {
occured[num] = true;
}
// 初始化答案
int ans = 0;
// 核心代码
// 遍历 occured 数组,i [1, maxVal],这个范围是最大公因数的范围
for (int i = 1; i <= maxVal; i++) {
// 设 当前 subGcd 为 0
int subGcd = 0;
// 暴力,j = i, j += i,此时 j 是 i 的倍数,j + i 也是 i 的倍数
for (int j = i; j <= maxVal; j += i) {
// 若当前下标 j 在 nums 中存在
if (occured[j]) {
// 若当前 subGcd 为零,说明刚遇到第一个 i 的倍数,设置当前的 subGcd = j
if (subGcd == 0) {
subGcd = j;
} else { // 遇到其他 i 的倍数,这时取最大公约数,就可能出现最大公约数 i
subGcd = gcd(subGcd, j);
}
// 如果,subGcd == i,说明存在最大公约数 i,累加一次
if (subGcd == i) {
ans++;
break; // 当前 i 值已经有符合条件的,则寻找下一个 i 是否有满足条件的子数组
}
// 否则继续循环寻找
}
}
}
return ans;
}
public int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
}