📜  GCD 1的最大子集(1)

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

GCD 1的最大子集

在数学上,最大公约数(GCD)指两个或多个整数共有约数中,最大的那个。

给定一个数组 nums,我们求出其中所有元素的最大公约数是否为 1。如果是,则求出最大的子集,使得子集中的元素的最大公约数也是 1。

基本思路

采用动态规划思想,定义一个数组 dp,其中 dp[i] 表示以 nums[i] 结尾的符合要求的最大子集大小。

初始状态为 dp[i]=1,因为一个数本身就是符合要求的最大子集,然后对于每个 dp[i],我们枚举 i 前面的所有数 j,如果 nums[i] 和 nums[j] 的最大公约数为 1,那么我们可以在 dp[j] 的基础上得到一个新的最大子集,即将 nums[i] 加入 dp[j] 中,那么此时 dp[i]=dp[j]+1。

最终答案为 dp 数组中的最大值。

代码
def gcd(a, b):
    if a < b:
        a, b = b, a
    while b != 0:
        a, b = b, a % b
    return a

def largestDivisibleSubset(nums: List[int]) -> List[int]:
    n = len(nums)
    nums.sort()
    dp = [1] * n
    pre = [-1] * n
    mmax = -1
    pos = -1
    for i in range(n):
        for j in range(i):
            if gcd(nums[i], nums[j]) == 1:
                if dp[j] + 1 > dp[i]:
                    dp[i] = dp[j] + 1
                    pre[i] = j
        if dp[i] > mmax:
            mmax = dp[i]
            pos = i

    res = []
    while pos != -1:
        res.append(nums[pos])
        pos = pre[pos]
    return res[::-1]
复杂度分析
  • 时间复杂度:$O(n^2logn)$,其中 n 是 nums 数组的长度。排序的时间复杂度为 $O(nlogn)$,枚举 i 和 j 的时间复杂度均为 $O(n^2)$,计算最大公约数的时间复杂度为 $O(log(max(nums)))$。因此总时间复杂度为 $O(n^2logn)$。
  • 空间复杂度:$O(n)$。需要使用 dp 数组和 pre 数组,它们的长度均为 n。