📜  门| GATE-CS-2014-(Set-1)|第65章(1)

📅  最后修改于: 2023-12-03 14:58:28.787000             🧑  作者: Mango

GATE-CS-2014-(Set-1) 第65题介绍

题目描述

给定一个整数数组A和一个整数k, 请你编写一个Python函数, 最多删除数组中的k个元素, 以使剩下的元素按照有效子序列的方式组成一个严格上升子序列。

输入格式

输入包含两行:

第一行包含一个整数n,表示数组A的长度。其中1 <= n <= 10^3

第二行包含n个整数,表示数组A中的元素。其中1 <= A[i] <= 10^3

第三行包含一个整数k,表示你最多可以删除k个元素。其中0 <= k <= n。

输出格式

输出一个整数,表示最多可以组成的有效子序列的长度。

示例

输入:

7
10 20 30 40 50 35 45
1

输出:

6

解释:可以删除数字35,得到一个有效的子序列:10 20 30 40 50 45。长度为6.

题解

此问题可以通过动态规划解决。

我们用len[i]来表示在前i个元素中创建的最长上升子序列的长度。

现在考虑在数据中删除元素的作用。在整个数组中, 有一个值d,使其(顺序地)被删除,那么:

  1. 如果d存在于上升子序列中,则整个上升子序列n不需要再去除其他元素。

  2. 如果d不在上升子序列中,则将n - 1扣减1(因为该元素不在最长子序列中,所以我们总是需要将至少一些元素删除)。

下面是本题的Python实现代码:

def max_length_subseq(a: list[int], k: int) -> int:
    n = len(a)
    # dp状态
    # len[i] 表示前i个元素中创建的最长上升子序列的长度
    len = [1] * n
    # 初始化
    res = 1

    # DP
    for i in range(1, n):
        for j in range(0, i):
            if a[i] > a[j]:
                len[i] = max(len[i], len[j] + 1)
        res = max(res, len[i])

    # 定义包含i元素时最长子序列长度的DP数组名为dp_i,
    # 然后返回n - dp_i = len - res + k 的最大值
    return max(len - res + k, 0)


# 测试
a = [10, 20, 30, 40, 50, 35, 45]
k = 1
print(max_length_subseq(a, k)) # 输出6

本程序模拟了根据删除元素进行求解的思路,其中DP算法中的dp[i]表示包含数组a中第i个元素时的最长上升子序列长度。

显然,dp[n-1]是最终的答案。 程序的核心是在n循环中计算dp数组,dp[i]只需在之前的已计算的dp[j]的加一基础上计算即可。