📅  最后修改于: 2023-12-03 15:41:17.882000             🧑  作者: Mango
给定一个整数数组,要求找到数组中所有数对的最小公倍数(LCM)。
对于每一对数,假设两数为a和b,则计算它们的最小公倍数即可。
时间复杂度O(n^2)
代码片段:
def lcm(a, b):
great = max(a, b)
while True:
if great % a == 0 and great % b == 0:
lcm = great
break
great += 1
return lcm
def min_lcm(arr):
min_lcm = float('inf')
for i in range(len(arr)):
for j in range(i+1, len(arr)):
min_lcm = min(min_lcm, lcm(arr[i], arr[j]))
return min_lcm
首先计算所有数的LCM。LCM为所有数的因子中次数最大的的各个素数的乘积。
然后对LCM的约数(包括1和LCM本身)进行枚举,找到其中两个数的最小公倍数即可。
时间复杂度O(n^2)
代码片段:
def gcd(a, b):
while b:
a, b = b, a % b
return a
def lcm(a, b):
return a * b // gcd(a, b)
def min_lcm(arr):
lcm_val = arr[0]
for i in range(1, len(arr)):
lcm_val = lcm(lcm_val, arr[i])
min_val = float('inf')
for i in range(1, int(lcm_val ** 0.5)+1):
if lcm_val % i == 0:
if i in arr:
for j in range(i+1, int(lcm_val/i)+1):
if j in arr:
min_val = min(min_val, i*j)
return min_val
对于每个数,记录下其所有素数的出现次数。使用一个Bitset来记录每个素数在每个数中出现的次数。
然后对于Bitset中上各个素数的次数,取最大值,则对应的素数的最大次数即为所求的LCM。
时间复杂度O(n*log2(n))
代码片段:
def min_lcm(arr):
max_val = max(arr)
primes = [True] * (max_val+1)
p = 2
while (p * p <= max_val):
if primes[p]:
for i in range(p * 2, max_val+1, p):
primes[i] = False
p += 1
bitset = [[0] * (max_val+1) for _ in range(len(arr))]
for i in range(len(arr)):
for j in range(2, arr[i]+1):
if primes[j]:
while arr[i]%j == 0:
bitset[i][j] += 1
arr[i] //= j
min_val = float('inf')
for i in range(2, max_val+1):
if primes[i]:
cnt = 0
for j in range(len(arr)):
cnt = max(cnt, bitset[j][i])
if cnt > 0:
min_val = min(min_val, i**cnt)
return min_val
方法1的时间复杂度最高,方法2的思路较为直接。方法3使用Bitset优化,在保证正确性的情况下时间复杂度更低。
建议如果n较小使用方法2,n较大使用方法3。