📌  相关文章
📜  给定阵列中所有对的最小LCM(1)

📅  最后修改于: 2023-12-03 15:41:17.882000             🧑  作者: Mango

给定阵列中所有对的最小LCM

简介

给定一个整数数组,要求找到数组中所有数对的最小公倍数(LCM)。

方法1:暴力枚举

对于每一对数,假设两数为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
方法2:求所有数的LCM,然后在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
方法3:使用Bitset记录素因子出现次数

对于每个数,记录下其所有素数的出现次数。使用一个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。