最长重复子数组的变种:允许最多k次元素替换的最长公共子数组
字数 1069 2025-11-08 10:02:38

最长重复子数组的变种:允许最多k次元素替换的最长公共子数组

题目描述
给定两个整数数组nums1和nums2,以及一个整数k。我们需要找到最长的公共子数组的长度,该子数组在nums1和nums2中出现,且允许在匹配过程中最多进行k次元素替换。这里的"替换"指的是如果nums1[i] ≠ nums2[j],我们可以将其视为匹配,但计入替换次数。

示例
输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7], k = 1
输出:3
解释:最长公共子数组是[3,2,1]或[2,3,1](替换1次)

解题过程

1. 问题分析
这是最长重复子数组问题的变种,增加了最多k次替换的灵活性。我们需要找到两个数组中的连续子数组,使得它们相似度最高(最多k个位置不同)。

2. 动态规划定义
定义dp[i][j][t]表示以nums1的第i个元素和nums2的第j个元素结尾的子数组,在使用恰好t次替换时的最大公共子数组长度。

3. 状态转移方程

  • 如果nums1[i-1] == nums2[j-1](匹配成功):
    dp[i][j][t] = dp[i-1][j-1][t] + 1
  • 如果nums1[i-1] != nums2[j-1](需要替换):
    当t > 0时,dp[i][j][t] = dp[i-1][j-1][t-1] + 1
    当t = 0时,dp[i][j][0] = 0(不能替换)
  • 边界情况:当i=0或j=0时,dp[i][j][t] = 0

4. 初始化

  • 创建三维数组dp[len1+1][len2+1][k+1]
  • 所有元素初始化为0

5. 填充DP表
我们按顺序遍历所有可能的状态:

for i in range(1, len1+1):
    for j in range(1, len2+1):
        for t in range(k+1):  # t从0到k
            if nums1[i-1] == nums2[j-1]:
                dp[i][j][t] = dp[i-1][j-1][t] + 1
            else:
                if t > 0:
                    dp[i][j][t] = dp[i-1][j-1][t-1] + 1
                else:
                    dp[i][j][t] = 0

6. 寻找最大值
我们需要在所有可能的替换次数(0到k)中找到最大值:

max_length = 0
for i in range(len1+1):
    for j in range(len2+1):
        for t in range(k+1):
            max_length = max(max_length, dp[i][j][t])

7. 空间优化
由于dp[i][j][t]只依赖于dp[i-1][j-1][t]和dp[i-1][j-1][t-1],我们可以使用二维数组进行空间优化:

# 使用两个二维数组交替计算
dp_prev = [[0]*(k+1) for _ in range(len2+1)]
dp_curr = [[0]*(k+1) for _ in range(len2+1)]

max_length = 0
for i in range(1, len1+1):
    for j in range(1, len2+1):
        for t in range(k+1):
            if nums1[i-1] == nums2[j-1]:
                dp_curr[j][t] = dp_prev[j-1][t] + 1
            else:
                if t > 0:
                    dp_curr[j][t] = dp_prev[j-1][t-1] + 1
                else:
                    dp_curr[j][t] = 0
            max_length = max(max_length, dp_curr[j][t])
    dp_prev, dp_curr = dp_curr, dp_prev  # 交换数组

8. 时间复杂度分析

  • 时间复杂度:O(len1 × len2 × k)
  • 空间复杂度:O(len2 × k)(优化后)

关键理解点

  1. 替换操作允许我们在元素不匹配时仍然可以延长公共子数组
  2. 替换次数t是累积的,需要记录在不同替换次数下的最优解
  3. 最终结果是所有可能替换次数下的最大值

这种方法通过动态规划巧妙地处理了替换操作,在保持算法效率的同时解决了复杂的匹配问题。

最长重复子数组的变种:允许最多k次元素替换的最长公共子数组 题目描述 给定两个整数数组nums1和nums2,以及一个整数k。我们需要找到最长的公共子数组的长度,该子数组在nums1和nums2中出现,且允许在匹配过程中最多进行k次元素替换。这里的"替换"指的是如果nums1[ i] ≠ nums2[ j ],我们可以将其视为匹配,但计入替换次数。 示例 输入:nums1 = [ 1,2,3,2,1], nums2 = [ 3,2,1,4,7 ], k = 1 输出:3 解释:最长公共子数组是[ 3,2,1]或[ 2,3,1 ](替换1次) 解题过程 1. 问题分析 这是最长重复子数组问题的变种,增加了最多k次替换的灵活性。我们需要找到两个数组中的连续子数组,使得它们相似度最高(最多k个位置不同)。 2. 动态规划定义 定义dp[ i][ j][ t ]表示以nums1的第i个元素和nums2的第j个元素结尾的子数组,在使用恰好t次替换时的最大公共子数组长度。 3. 状态转移方程 如果nums1[ i-1] == nums2[ j-1 ](匹配成功): dp[ i][ j][ t] = dp[ i-1][ j-1][ t ] + 1 如果nums1[ i-1] != nums2[ j-1 ](需要替换): 当t > 0时,dp[ i][ j][ t] = dp[ i-1][ j-1][ t-1 ] + 1 当t = 0时,dp[ i][ j][ 0 ] = 0(不能替换) 边界情况:当i=0或j=0时,dp[ i][ j][ t ] = 0 4. 初始化 创建三维数组dp[ len1+1][ len2+1][ k+1 ] 所有元素初始化为0 5. 填充DP表 我们按顺序遍历所有可能的状态: 6. 寻找最大值 我们需要在所有可能的替换次数(0到k)中找到最大值: 7. 空间优化 由于dp[ i][ j][ t]只依赖于dp[ i-1][ j-1][ t]和dp[ i-1][ j-1][ t-1 ],我们可以使用二维数组进行空间优化: 8. 时间复杂度分析 时间复杂度:O(len1 × len2 × k) 空间复杂度:O(len2 × k)(优化后) 关键理解点 替换操作允许我们在元素不匹配时仍然可以延长公共子数组 替换次数t是累积的,需要记录在不同替换次数下的最优解 最终结果是所有可能替换次数下的最大值 这种方法通过动态规划巧妙地处理了替换操作,在保持算法效率的同时解决了复杂的匹配问题。