代码随想录笔记_动态规划_718最长重复子数组

代码随想录二刷笔记记录

LC718.最长重复子数组


题目

子序列问题

给两个整数数组 nums1 和 nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度 。

示例 1:

输入:nums1 = [1,2,3,2,1], nums2 = [3,2,1,4,7]
输出:3
解释:长度最长的公共子数组是 [3,2,1] 。

示例 2:

输入:nums1 = [0,0,0,0,0], nums2 = [0,0,0,0,0]
输出:5


思路分析

思路

子数组问题,可以理解为子序列问题 -> 动态规划

A = [1,2,3,2,1], B = [3,2,1,4,7]
具体思路:
把A的元素逐个和B中的元素遍历,如果遇到 A[i] = B[j] ,则继续比较 A[i+1] 和 B[j+1] ,将 dp + 1 ,否则,dp长度保持不变。

例如: A[0] = B[2] ,则拿A[1] 和 B[3] 继续比较,A[1] != B[3] 则停止,继续遍历A[2]和B[0] - B[4]

动态规划五部曲

1.确定dp数组及其下标的含义

dp[i][j] : 以下标 i-1 结尾的数组A,和以下标 j-1 结尾的数组B,最长重复子数组的长度
注意,dp[0][0] 无意义,仅是为了增维,使得计算方便。详见5.推演分析

2.确定递推公式

//根据dp[i][j] 的定义,可知,
//dp[i][j] 由 dp[i-1][j-1] 推导而来
//当 A[i-1] 和 B[j-1] 相等时,更新dp[i][j]
if(A[i-1] == B[j-1]){
	dp[i][j] = dp[i-1][j-1] + 1;
}

3.初始化

假设:A[0] = B[0], 则 dp[1][1] 需由 dp[0][0] + 1,因此 dp[0][0] 需要初始化为0。
推广可知,dp[i][0] 和 dp[0][j] 同理,都要初始化为0。

4.遍历顺序

根据递推公式可知,从前往后遍历。
具体:先遍历A,拿着A的元素,再遍历B。

for (int i = 1; i <= lenA; i++) {
     for (int j = 1; j <= lenB; j++) {
         if (nums1[i-1] == nums2[j-1]){
         	dp[i][j] = dp[i-1][j-1] + 1;
         }
         max = Math.max(dp[i][j],max);
        }
 }

5.推演分析

以 A = [1,2,3,2,1], B = [3,2,1,4,7] 为例

请添加图片描述

B(j)32147
A(i)000000
1000100
2001000
3010000
2002000
1000300

代码实现

完整代码实现

public int findLength(int[] nums1, int[] nums2) {
        int lenA = nums1.length;
        int lenB = nums2.length;
        if (lenA == 0 || lenB == 0) return 0;
        //初始化
        int[][] dp = new int[lenA+1][lenB+1];
        //遍历
        int max = 0;
        for (int i = 1; i <= lenA; i++) {
            for (int j = 1; j <= lenB; j++) {
                if (nums1[i-1] == nums2[j-1]){
                    dp[i][j] = dp[i-1][j-1] + 1;
                }
                max = Math.max(dp[i][j],max);
            }
        }
        return max;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值