最长重复子数组的变种:允许最多k次元素删除的最长公共子数组
字数 1128 2025-11-15 22:59:28
最长重复子数组的变种:允许最多k次元素删除的最长公共子数组
题目描述
给定两个整数数组nums1和nums2,以及一个整数k。我们需要找到最长的公共子数组,该子数组在nums1中可以通过删除最多k个元素得到。换句话说,我们需要找到最长的连续子数组,该子数组同时出现在nums1和nums2中,但在nums1中允许最多跳过k个元素。
解题过程
这个问题是经典最长公共子数组问题的变种,增加了在第一个数组中最多跳过k个元素的灵活性。让我们通过动态规划来逐步解决。
步骤1:定义状态
我们定义dp[i][j][d]表示以nums1的第i个元素和nums2的第j个元素结尾,且已经跳过了d个元素的最长公共子数组长度。
步骤2:状态转移方程
考虑当前比较的元素nums1[i-1]和nums2[j-1]:
- 如果两个元素相等:
- 我们可以直接扩展前一个公共子数组:dp[i][j][d] = dp[i-1][j-1][d] + 1
- 或者,如果我们选择跳过nums1中的当前元素(如果d > 0):dp[i][j][d] = dp[i-1][j][d-1]
- 或者,如果我们选择跳过nums2中的当前元素:dp[i][j][d] = dp[i][j-1][d-1]
- 如果两个元素不相等:
- 我们可以跳过nums1中的当前元素(如果d > 0):dp[i][j][d] = dp[i-1][j][d-1]
- 或者跳过nums2中的当前元素(如果d > 0):dp[i][j][d] = dp[i][j-1][d-1]
- 或者重新开始:dp[i][j][d] = 0
步骤3:初始化
- 当i=0或j=0时,dp[i][j][d] = 0(没有元素可以比较)
- 当d=0且i,j>0时,如果nums1[i-1] == nums2[j-1],则dp[i][j][0] = dp[i-1][j-1][0] + 1,否则为0
步骤4:计算顺序
我们按i从1到n,j从1到m,d从0到k的顺序计算dp值。
步骤5:结果提取
最终结果是所有dp[i][j][d]中的最大值。
优化思路
由于三维DP的空间复杂度较高,我们可以优化为二维DP:
定义dp[i][j]表示以nums1的第i个元素和nums2的第j个元素结尾的最长公共子数组长度,同时使用一个额外的数组来记录删除次数。
实际实现
在实际实现中,我们可以使用二维DP,并通过遍历所有可能的删除次数来找到最优解。
这个算法的时间复杂度是O(n×m×k),空间复杂度通过优化可以降低到O(m×k)。