📌  相关文章
📜  重复删除LIS后的阵列大小(1)

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

重复删除LIS后的阵列大小

当我们需要找到一个数列中最长的递增子序列(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)

以上便是两种不同的解决方法,使用时可根据具体情况选择适合的方法。