📅  最后修改于: 2023-12-03 15:10:43.054000             🧑  作者: Mango
在解决算法问题时,找到最长子序列是很常见的问题。这里介绍如何查找LCM最多为K的阵列的最长子序列。
最长子序列(LCS)指的是两个或多个长度为任意的序列中,最长公共子序列的长度。最长公共子序列问题是区分于最长公共子串问题的另一类问题。相对于子串而言,子序列不要求连续。例如字符串“acdfg”与“adfcg”的最长公共子序列长度为3(即“dfg”)。
LCM(Least Common Multiple)即最小公倍数,是指两个或多个整数的公共倍数中最小的一个。例如2和3的公倍数为6,12等,其中6为最小公倍数。
下面介绍如何查找LCM最多为K的阵列的最长子序列。
根据LCM的定义,我们可以得出一个结论:当一个数是LCM的倍数时,它的任何子序列都是LCM的倍数。
计算每个数的因数,即第i个数能被哪些数整除。设其因数为divisions[i],则divisions[i]为一个列表。
设dp[i][j]表示当LCS的长度为i、以第j个数结尾时,满足所有子串的最小公倍数都不超过K的LCS的长度。例如dp[3][5]表示以第5个数结尾、LCS的长度为3时,满足所有子串的最小公倍数都不超过K的LCS的长度。
遍历数组,对于每个dp[i][j],它的值为dp[i-1][k] + 1,其中k表示divisions[j]中的一个数。
最终的结果为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
返回的是最长的子序列长度,如果想要获取最长子序列,则需要稍作修改。