📅  最后修改于: 2023-12-03 15:26:38.092000             🧑  作者: Mango
在给定的整数数组中,可能存在多个整数对,每对整数的GCD是整数对中的两个数的最大公约数。 本文将介绍如何查找数组中所有整数对的最小GCD。
一种简单的方法是使用嵌套循环,在数组中枚举所有可能的整数对,计算它们的最大公约数并统计其最小值。
def find_min_gcd(nums):
n = len(nums)
min_gcd = float('inf')
for i in range(n):
for j in range(i+1, n):
gcd = math.gcd(nums[i], nums[j])
min_gcd = min(min_gcd, gcd)
return min_gcd
该算法的时间复杂度为$O(n^2)$,空间复杂度为$O(1)$,适用于数据量较小的情况。
由于整数对的数量是$O(n^2)$级别的,优化枚举算法的关键是减少不必要的计算。有一种常见的技巧是,先计算数组中所有数的最大值和最小值,然后使用辗转相除法计算这些数的最大公约数,然后在原数组中查找最小公约数的倍数。这是因为一个大于最小公约数的数,不可能是数组中任何整数对的GCD。
def find_min_gcd(nums):
n = len(nums)
min_val, max_val = min(nums), max(nums)
gcd_val = math.gcd(min_val, max_val)
multiples = [i*gcd_val for i in range(1, max_val//gcd_val+1)]
for m in multiples:
count = sum(1 for num in nums if num % m == 0)
if count >= 2:
return m
return -1
该算法的时间复杂度为$O(n\log V)$,其中$V$是数组中最大值和最小值的差值。空间复杂度为$O(V/\gcd)$,其中$\gcd=min_val$和$max_val$的最大公约数。适用于数据量较大的情况。
另一种方法是使用哈希表,将数组中所有数的约数存储在哈希表中。对于任何一个约数$x$,在哈希表中查找是否存在不同的整数对,它们的最大公约数是$x$。为了避免重复计算,我们只需要枚举一个整数$a$,它比最小公约数大且还是$x$的倍数。
def find_min_gcd(nums):
n = len(nums)
divisor_dict = defaultdict(list)
for num in nums:
for d in range(1, int(num**0.5)+1):
if num % d == 0:
divisor_dict[d].append(num)
if d != num // d:
divisor_dict[num//d].append(num)
for d in sorted(divisor_dict.keys(), reverse=True):
if len(divisor_dict[d]) >= 2:
for i in range(1, len(divisor_dict[d])):
a, b = divisor_dict[d][-i-1], divisor_dict[d][-i]
if a < b:
a, b = b, a
if b == d or b % d != 0:
continue
for x in range(d*(b//d), b, d):
if x > a and x % d == 0:
return d
return -1
该算法的时间复杂度为$O(n\sqrt{V}\log V)$,其中$V$是数组中最大值和最小值的差值。空间复杂度为$O(n\log V)$。它适用于任何数据量,但在实际应用中可能不如前两种方法快。