Java 中不同子序列的 GCD

2024年9月10日 | 阅读 6 分钟

给定一个包含正数的数组 inArr。任务是找到输入数组中所有存在的子序列中不同的 GCD(最大公约数)的数量。注意,数组的子序列是通过一次选取一个或多个元素形成的。

示例 1

输入

int inArr[] = {6, 8, 10}

输出 4

解释:输入数组的不同子序列及其 GCD 为

对于子序列 {6},GCD 为 6。

对于子序列 {8},GCD 为 8。

对于子序列 {10},GCD 为 10。

对于子序列 {6, 8},GCD 为 2。

对于子序列 {8, 10},GCD 为 2。

对于子序列 {6, 10},GCD 为 2。

对于子序列 {6, 8, 10},GCD 为 2。

因此,所有计算出的 GCD 为 6、8、10、2、2、2、2,其中只有 4 个是唯一的(6、8、10、2)。因此,输出为 4。

示例 2

输入

int inArr[] = {2, 4, 8}

输出 3

解释:输入数组的不同子序列及其 GCD 为

对于子序列 {2},GCD 为 2。

对于子序列 {4},GCD 为 4。

对于子序列 {8},GCD 为 8。

对于子序列 {2, 4},GCD 为 2。

对于子序列 {4, 8},GCD 为 4。

对于子序列 {2, 8},GCD 为 2。

对于子序列 {2, 4, 8},GCD 为 2。

因此,所有计算出的 GCD 为 2、4、8、2、4、2、2,其中只有 3 个是唯一的(2、4、8)。因此,输出为 3。

方法:暴力法

在此方法中,我们将计算输入数组的所有子序列,并将这些子序列存储在 ArrayList 中。然后,我们将计算存储在 ArrayList 中的所有子序列的 GCD,并将它们放入一个 Set 中。由于 Set 只包含唯一元素,Set 的大小就是我们的答案。为了找到子序列,我们将使用递归。观察以下程序。

文件名:DiffSubseqGCD.java

输出

For the input array: 
6 8 10 
The total number of unique GCDs is: 4

For the input array: 
2 4 8 
The total number of unique GCDs is: 3

复杂度分析:每次递归调用都会导致另外两次递归调用。因此,程序的 time complexity 是指数级的。程序的 space complexity 也是指数级的。

上述程序不适用于较大的输入,因为程序的 time complexity 和 space complexity 都太高了。因此,我们必须进行一些优化来降低 time complexity 和 space complexity。

高效方法

使用贪心方法,我们可以进行优化。我们必须利用这样的事实:任何两个数字 n1 和 n2 的 GCD 介于 1 到 max(n1, n2) 之间,并且对于包含两个以上元素的任何子序列,相同的概念也成立。如果子序列中的最大元素是 M,则 GCD 始终落在 [1, M] 的范围内。因此,我们可以从 1 到 M 进行迭代,如果给定范围内的任何数字是数组中某个元素的因子,那么我们可以将该元素显示为 GCD 的一个结果。

文件名:DiffSubseqGCD1.java

输出

For the input array: 
6 8 10 
The total number of unique GCDs is: 4

For the input array: 
2 4 8 
The total number of unique GCDs is: 3

复杂度分析:程序的 time complexity 为 O(Max * log(Max)),其中 Max 是数组的最大元素。程序的 space complexity 为 O(N),其中 N 是 ArrayList 中存在的元素总数。