📅  最后修改于: 2023-12-03 15:42:05.719000             🧑  作者: Mango
当我们需要找到一个数列中最长的递增子序列(LIS)时,可以使用动态规划的思想来解决。但是在某些情况下,我们会需要删除LIS中的重复元素,最后得到新的数列大小,那么这个大小如何计算呢?
一种简单的方法是,在找到LIS后,直接遍历删除其中出现过的元素,最后返回新数列的大小。
代码片段如下(Python实现):
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)
max_len = max(dp)
lis_seq = []
for i in range(n-1, -1, -1):
if dp[i] == max_len:
lis_seq.append(arr[i])
max_len -= 1
return len(list(reversed(lis_seq)))
def remove_duplicates_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)
max_len = max(dp)
lis_seq = []
for i in range(n-1, -1, -1):
if dp[i] == max_len:
lis_seq.append(arr[i])
max_len -= 1
for i in lis_seq:
while arr.count(i) > 1:
arr.remove(i)
return len(arr)
另一种方法是,在找到LIS的同时,记录各元素在LIS中的位置。然后遍历LIS,将其中出现过的元素在原数列中删除,最后返回新数列的大小。
代码片段如下(Python实现):
def lis(arr):
n = len(arr)
dp = [1] * n
pos = [[i] for i in range(n)]
for i in range(1, n):
for j in range(i):
if arr[i] > arr[j]:
if dp[j] + 1 > dp[i]:
dp[i] = dp[j] + 1
pos[i] = pos[j] + [i]
elif dp[j] + 1 == dp[i]:
pos[i] = min(pos[j] + [i], pos[i], key=lambda x: arr[x[-1]])
max_len = max(dp)
lis_seq = []
for i in range(n):
if len(pos[i]) == max_len:
lis_seq = pos[i]
break
return lis_seq
def remove_duplicates_lis(arr):
lis_seq = lis(arr)
for i in lis_seq:
while arr.count(arr[i]) > 1:
arr.remove(arr[i])
return len(arr)
以上便是两种不同的解决方法,使用时可根据具体情况选择适合的方法。