📅  最后修改于: 2023-12-03 15:26:28.556000             🧑  作者: Mango
最长子序列和最大GCD是两个经典的算法问题。
最长子序列指的是一个序列中的一段连续子序列,并且该子序列的长度最长。
对于一个给定的序列,最长子序列有多种求解方案,其中比较经典的有动态规划和贪心算法。
动态规划的思路是,从头开始遍历整个序列,对于每个位置,把当前位置的数选或不选,分别求出相应的最长子序列长度,并记录下来。最终,最长的那个子序列长度即为所求。
贪心算法的思路是,从头开始遍历整个序列,维护两个变量:当前子序列长度和当前子序列的和。对于每个位置,如果当前子序列的和加上该位置的数仍小于等于该位置的数,那么就把该位置的数加入当前子序列,否则就另起一个子序列。最终,所有生成的子序列中长度最长的即为所求。
最大GCD指的是一个序列中任意两个数的最大公约数的最大值。
对于一个给定的序列,最大GCD也有多种求解方案,其中经典的有暴力和欧几里得算法。
暴力的思路是,枚举所有的数对,并求出它们的最大公约数,再选出其中最大的那个。时间复杂度为$O(n^2logn)$。
欧几里得算法的思路是,设$m$为所求数组的最大值,然后从$m$开始向下枚举,对于每个枚举到的数$x$,判断数组中是否至少存在两个数$y$和$z$,使得它们的最大公约数为$x$。如果存在,那么$x$即为所求。否则,继续往下枚举。时间复杂度为$O(nlogm)$。
将最长子序列和最大GCD结合起来,即在一个序列中寻找一个最长的连续子序列,并且该子序列中任意两个数的最大公约数等于$k$。这个问题可以用动态规划和欧几里得算法结合起来求解。
具体来说,设$dp[i][j]$表示在序列的前$i$个元素中,以第$i$个元素结尾的符合要求的最长子序列长度,其中任意两个元素的最大公约数等于$j$。对于$dp[i][j]$,更新方式有两种情况:
最终,所求即为$dp$数组中的最大值。时间复杂度为$O(nk\log m)$。
下面是用python实现最长子序列和最大GCD的代码。
def get_largest_subsequence(nums, k):
n = len(nums)
dp = [[0] * (k+1) for _ in range(n)]
res = 1
for i in range(n):
dp[i][nums[i]] = 1
for j in range(nums[i]+1, k+1):
dp[i][j] = dp[i-1][j] if j % nums[i] else max(dp[i-1][j], dp[i-1][j//nums[i]] + 1)
res = max(res, dp[i][k])
return res
def get_max_gcd(nums):
m = max(nums)
for x in range(m, 0, -1):
cnt = 0
for y in nums:
if y % x == 0:
cnt += 1
if cnt == 2:
return x
return 1
def get_largest_subsequence_with_max_gcd(nums, k):
gcd = get_max_gcd(nums)
if gcd > k:
return 0
nums = [num//gcd for num in nums]
k //= gcd
return get_largest_subsequence(nums, k) * gcd
以上是完整代码。
Markdown片段如下:
# 最长子序列和最大GCD介绍
最长子序列和最大GCD是两个经典的算法问题。
## 最长子序列
......
## 最大GCD
......
## 综合应用
将最长子序列和最大GCD结合起来,即......
## CODE
下面是用python实现最长子序列和最大GCD的代码。
```python
......
以上是完整代码。