📅  最后修改于: 2023-12-03 15:32:43.633000             🧑  作者: Mango
LIS(最长上升子序列)问题是一个常见的动态规划问题。给定一个序列,找到其中最长的递增子序列。但是,这个问题有许多变化形式,本文将介绍这些变化和它们的解决方案。
最长下降子序列问题与LIS问题很相似,但是要求递减。例如,在序列[3,2,1,4,5,2,3]中,最长递减子序列为[3,2,1]或[5,2],长度为3。
最长不下降子序列问题允许序列中相同的数字出现在不同的位置。例如,在序列[1,3,2,2,4,1]中,最长不下降子序列为[1,2,2,4],长度为4。
最长公共子序列问题要求在两个序列中找到最长的相同子序列。例如,在序列[1,2,3,4,5]和[2,4,3,1,5]中,最长公共子序列为[2,3,5],长度为3。
最长连续递增子序列问题要求在一个序列中找到最长的连续递增子序列。例如,在序列[1,2,3,1,2,3,4,5,6]中,最长连续递增子序列为[4,5,6],长度为3。
最长连续不下降子序列问题要求在一个序列中找到最长的连续不下降子序列。例如,在序列[1,2,3,2,3,3,4,5]中,最长连续不下降子序列为[2,3,3,4,5],长度为5。
最长下降子序列可以通过将序列反转来转换为LIS问题,并应用LIS的解决方案。也可以通过DP解决。
def LDS(arr):
n = len(arr)
dp = [1]*n
for i in range(1, n):
for j in range(i):
if arr[i] < arr[j]:
dp[i] = max(dp[i], dp[j]+1)
return max(dp)
最长不下降子序列可以通过将序列分组来转换为多个LIS问题,并应用LIS的解决方案。
def LNDS(arr):
groups = []
for a in arr:
added = False
for g in groups:
if a >= g[-1]:
g.append(a)
added = True
break
if not added:
groups.append([a])
return sum([LIS(group) for group in groups])
def LIS(arr):
n = len(arr)
dp = [1]*n
for i in range(1, n):
for j in range(i):
if arr[i] > arr[j]:
dp[i] = max(dp[i], dp[j]+1)
return max(dp)
最长公共子序列可以通过DP解决。
def LCS(s1, s2):
m, n = len(s1), len(s2)
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(1, m+1):
for j in range(1, n+1):
if s1[i-1] == s2[j-1]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
return dp[m][n]
最长连续递增子序列可以通过遍历序列来计算。
def LCIS(arr):
n = len(arr)
ans, cur = 1, 1
for i in range(1, n):
if arr[i] > arr[i-1]:
cur += 1
ans = max(ans, cur)
else:
cur = 1
return ans
最长连续不下降子序列可以通过遍历序列来计算。
def LNCIS(arr):
n = len(arr)
ans, cur = 1, 1
for i in range(1, n):
if arr[i] >= arr[i-1]:
cur += 1
ans = max(ans, cur)
else:
cur = 1
return ans
本文介绍了LIS问题的几种变化形式,以及它们的解决方案。这些问题都可以使用动态规划来解决,但是需要针对每个特定的问题进行适当的调整。在实际应用中,需要根据具体情况来选择最适合的方法。