You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

61 lines
1.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2022_06_2_week;
// 给你一个由正整数组成的数组 nums 。
// 数字序列的 最大公约数 定义为序列中所有整数的共有约数中的最大整数。
// 例如,序列 [4,6,16] 的最大公约数是 2 。
// 数组的一个 子序列 本质是一个序列,可以通过删除数组中的某些元素(或者不删除)得到。
// 例如,[2,5,10] 是 [1,2,1,2,4,1,5,10] 的一个子序列。
// 计算并返回 nums 的所有 非空 子序列中 不同 最大公约数的 数目 。
// 测试链接 : https://leetcode.com/problems/number-of-different-subsequences-gcds/
public class Code03_NumberOfDifferentSubsequencesGCDs {
// n不是数字的个数是数组中的最大值
// 体系学习班,
// 根据数据量猜解法,
// 要想通过测试一定要让计算量不超过10的7次方~10的8次方
// n/1 + n/2 + n/3 + n/4 + ... + n/n -> O(N * logN)
public static int countDifferentSubsequenceGCDs(int[] nums) {
// 找到数组中的最大数max
int max = Integer.MIN_VALUE;
for (int num : nums) {
max = Math.max(max, num);
}
// 1~max哪个数有哪个数没有
boolean[] set = new boolean[max + 1];
for (int num : nums) {
set[num] = true;
}
int ans = 0;
// a是当前想确定是不是某个子序列的最大公约数有a
for (int a = 1; a <= max; a++) {
// 1)找到离a最近的a的倍数1 2 3 ... g就是
int g = a;
for (; g <= max; g += a) {
if (set[g]) {
break;
}
}
// 2) 找到了a最近的倍数g
// g + 0 , g ?= a
// g + a , g ?= a
// g + 2a , g ?= a
// g + 3a , g ?= a
for (int b = g; b <= max; b += a) {
if (set[b]) {
g = gcd(g, b);
if (g == a) {
ans++;
break;
}
}
}
}
return ans;
}
public static int gcd(int m, int n) {
return n == 0 ? m : gcd(n, m % n);
}
}