最长重复子数组的变种:允许最多k次元素删除的最长公共子数组
字数 1019 2025-11-15 14:24:58
最长重复子数组的变种:允许最多k次元素删除的最长公共子数组
题目描述:
给定两个整数数组nums1和nums2,以及一个非负整数k。我们需要找到两个数组中相同的最长子数组(连续子数组),但是在匹配过程中允许最多删除k个元素。也就是说,我们可以从两个数组的任意位置删除最多k个元素,使得剩下的子数组完全相同,并且长度最长。
解题过程:
- 问题分析:
- 这是一个最长公共子数组问题的变种,增加了删除操作的灵活性
- 与标准最长公共子数组不同,我们允许跳过(删除)最多k个不匹配的元素
- 我们需要找到最长的连续公共子数组,考虑删除操作
-
动态规划状态定义:
定义dp[i][j][d]表示以nums1的第i个元素和nums2的第j个元素结尾,使用了d次删除操作时,能够获得的最长公共子数组长度。 -
状态转移方程:
- 如果nums1[i-1] == nums2[j-1](当前元素匹配):
dp[i][j][d] = dp[i-1][j-1][d] + 1 - 如果nums1[i-1] != nums2[j-1](当前元素不匹配):
- 如果d > 0(还有删除次数可用):
dp[i][j][d] = max(dp[i-1][j][d-1], dp[i][j-1][d-1]) - 如果d = 0(没有删除次数可用):
dp[i][j][d] = 0
- 如果d > 0(还有删除次数可用):
- 初始化:
- 当i=0或j=0时,dp[i][j][d] = 0(空数组)
-
空间优化:
由于状态转移只依赖于前一行和前一列,我们可以使用二维数组进行空间优化,通过倒序遍历来避免状态覆盖。 -
算法步骤:
步骤1:初始化二维数组dp,大小为(len(nums2)+1) × (k+1)
步骤2:遍历nums1的每个元素
步骤3:对于每个nums1元素,倒序遍历nums2
步骤4:对于每个删除次数d(从k到0倒序)
步骤5:根据状态转移方程更新dp值
步骤6:记录过程中出现的最大值 -
时间复杂度:O(n×m×k),其中n、m分别是两个数组的长度
空间复杂度:O(m×k) -
边界情况处理:
- 当k=0时,退化为标准的最长公共子数组问题
- 当k足够大时,相当于找到两个数组的最长公共子序列
- 处理空数组的情况
这个解法通过动态规划巧妙地处理了删除操作的限制,在标准最长公共子数组的基础上增加了删除次数的维度,使得我们能够在允许有限次删除的情况下找到最长的公共子数组。