LeetCode 718.最长重复子数组

题目描述

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

示例 1:

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

说明:
1 <= len(A), len(B) <= 1000
0 <= A[i], B[i] < 100

使用算法

使用动态规划(Dynamic Programming)算法:

  • 递归到动态规划的一般转化方法
    递归函数有n个参数,就定义一个n维数组,数组的下标是递归函数参数的取值范围,数组元素的值是递归函数的返回值,这样就可以从边界值开始,逐步填充数组,相当于计算递归函数值的逆过程。
  • 能用动态规划解决的问题的特点:
    1.问题具有最优子结构性质
    2.无后效性
  • 动态规划解题的一般步骤:
    1.将原问题分解为子问题
    2.确定状态
    3.确定一些初始状态(边界状态)的值
    4.确定状态转移方程

解题思路

  • 分割子问题
    设DP[i][j]矩阵表示以A[i-1]和B[j-1]为结尾元素的公共子数组的长度(注意:在最后形成的公共子数组结果中,最后一个元素必须为A[i-1]和B[j-1],而不是说以A[i-1]和B[j-1]结尾的子数组再去寻找公共子数组)。
  • 确定边界条件
    DP[0][j]和DP[i][0]分别表示A和B为空串,显然结果都为0,以此作为边界条件。
  • 分情况讨论递推公式:
    当新增加的元素使两个子数组结尾元素相同时,DP[i][j]=DP[i-1][j-1]。
    当新增加的元素使两个子数组结尾元素不同时,因为不可能存在结尾不同的公共子数组,所以DP[i][j]=0。
    对于题目所给示例而言,DP矩阵如下:
A\B空串32147
空串000000
1000100
2001000
3010000
2002000
1000300
  • 确定原问题与子问题关系
    因为最后形成的最长公共子数组,一定是以A中某个元素结尾,B中某个原素结尾。所以最终所求问题,等价于寻找DP矩阵中最大元素,其对应的值即为最长公共子数组的长度。
  • C++代码:
    class Solution {
    public:
        int findLength(vector<int>& A, vector<int>& B) {
            int Max = 0;
            int lenA = A.size();
            int lenB = B.size();
            vector<vector<int>> DP(lenA + 1, vector<int>(lenB + 1, 0));
    
            //设置边界条件
            for(int i = 0; i <= lenA; i++)
            {
                DP[i][0] = 0;
            }
            for(int j = 0; j <= lenB; j++)
            {
                DP[0][j] = 0;
            }
    
            for(int i = 1; i <= lenA; i++)
            {
                for(int j = 1; j <= lenB; j++)
                {
                    if(A[i - 1] == B[j - 1])
                    {
                        DP[i][j] = DP[i- 1][j - 1] + 1;
                    }
                    else
                    {
                        DP[i][j] = 0;
                    }
                    Max = Max > DP[i][j] ? Max : DP[i][j];
                }
            }
    
            return Max;
        }
    };
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值