📜  查找LCM最多为K的阵列的最长子序列(1)

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

查找LCM最多为K的阵列的最长子序列

在解决算法问题时,找到最长子序列是很常见的问题。这里介绍如何查找LCM最多为K的阵列的最长子序列。

什么是最长子序列?

最长子序列(LCS)指的是两个或多个长度为任意的序列中,最长公共子序列的长度。最长公共子序列问题是区分于最长公共子串问题的另一类问题。相对于子串而言,子序列不要求连续。例如字符串“acdfg”与“adfcg”的最长公共子序列长度为3(即“dfg”)。

LCM是什么?

LCM(Least Common Multiple)即最小公倍数,是指两个或多个整数的公共倍数中最小的一个。例如2和3的公倍数为6,12等,其中6为最小公倍数。

算法流程

下面介绍如何查找LCM最多为K的阵列的最长子序列。

  1. 根据LCM的定义,我们可以得出一个结论:当一个数是LCM的倍数时,它的任何子序列都是LCM的倍数。

  2. 计算每个数的因数,即第i个数能被哪些数整除。设其因数为divisions[i],则divisions[i]为一个列表。

  3. 设dp[i][j]表示当LCS的长度为i、以第j个数结尾时,满足所有子串的最小公倍数都不超过K的LCS的长度。例如dp[3][5]表示以第5个数结尾、LCS的长度为3时,满足所有子串的最小公倍数都不超过K的LCS的长度。

  4. 遍历数组,对于每个dp[i][j],它的值为dp[i-1][k] + 1,其中k表示divisions[j]中的一个数。

  5. 最终的结果为dp[i][j]中最大的值。

代码

下面是基于上述思路的代码片段:

def find_longest_subsequence(arr, k):
    n = len(arr)

    # 计算每个数的因数
    divisions = [[] for _ in range(n)]
    for i in range(n):
        for j in range(i+1, n):
            if arr[j] % arr[i] == 0:
                divisions[j].append(i)

    # 初始化dp数组
    dp = [[0] * n for _ in range(k+1)]
    res = 0

    # 遍历数组
    for i in range(1, k+1):
        for j in range(n):
            for div in divisions[j]:
                dp[i][j] = max(dp[i][j], dp[i-1][div] + 1)
            res = max(res, dp[i][j])

    return res

返回的是最长的子序列长度,如果想要获取最长子序列,则需要稍作修改。