📌  相关文章
📜  最小化要添加到给定数组中的元素,使其包含另一个给定数组作为其子序列|套装2(1)

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

最小化要添加到给定数组中的元素,使其包含另一个给定数组作为其子序列|套装2

问题描述

给定两个数组 targetarr,要求通过向 arr 中添加一些元素,使得 arr 包含 target 作为其子序列,并且添加的元素数量最小。

解题思路

这是一道经典的动态规划问题。我们可以定义状态 $dp_{i,j}$ 表示让 arr[0..i] 包含 target[0..j] 的最小添加次数。则最终答案为 $dp_{n-1,m-1}$,其中 $n$ 和 $m$ 分别为 arrtarget 的长度。

接下来,我们考虑如何转移。如果当前 arr[i]target[j] 相等,则 $dp_{i,j}=dp_{i-1,j-1}$,因为不需要添加额外元素即可匹配。如果不相等,则可以考虑在 arr[i] 上添加一个元素,使得 arr[0..i-1] 包含 target[0..j],即 $dp_{i,j}=dp_{i-1,j}+1$。特别地,当 $j=0$ 时,对应的状态只需要判断当前 arr[i] 是否等于 target[0] 即可,也就是 $dp_{i,0}=dp_{i-1,0}+1$。

最终,我们遍历数组 arrtarget,计算所有状态 $dp_{i,j}$,并记录其中的最小值即可。时间复杂度为 $O(nm)$。

代码示例
def minOperations(target: List[int], arr: List[int]) -> int:
    m, n = len(target), len(arr)
    dp = [[0] * (m + 1) for _ in range(n + 1)]
    
    for i in range(1, n+1):
        for j in range(1, m+1):
            if arr[i-1] == target[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 m - dp[n][m]

代码中,我们使用 dp[i][j] 表示让 arr[0..i-1] 包含 target[0..j-1] 的最小添加次数。其中,arrtarget 的角标都是从0开始的,这一点需要注意。