算法——最长重复子数组(动态规划)

给两个整数数组 nums1nums2 ,返回 两个数组中 公共的 、长度最长的子数组的长度

. - 力扣(LeetCode)

方法:动态规划.

dp[i][j] 表示,第一个数组的索引i与第二个数组索引j所在位置的元素,从两个数组该位置开始一直到最后相同元素的最大长度。显然如果该位置二者不相等则dp数组值为0.若相等,则weidp[i+1][j+1]+1,即该位置相等,至少为1,加上二者后一个位置的最大长度。这就是状态转移方程。

官方代码一如既往的精简。

在申请数组时多申请一行一列,且赋值为零,在正常范围内计算时如果需要加上也是加上零,无影响。代码精炼,赞。

在涉及到边界条件且与内部情况不一致时,可以添加外层边界,让边界参与同样的计算。(链表增加虚拟头结点也是这样的原理)

复制代码
class Solution {
public:
    int findLength(vector<int>& A, vector<int>& B) {
        int n = A.size(), m = B.size();
        vector<vector<int>> dp(n + 1, vector<int>(m + 1, 0));
        int ans = 0;
        for (int i = n - 1; i >= 0; i--) {
            for (int j = m - 1; j >= 0; j--) {
                dp[i][j] = A[i] == B[j] ? dp[i + 1][j + 1] + 1 : 0;
                ans = max(ans, dp[i][j]);
            }
        }
        return ans;
    }
};

附上菜鸡自己的:(原来二维vector数组也是可以直接初始化的)

复制代码
class Solution {
public:
    int findLength(vector<int>& nums1, vector<int>& nums2) {
        vector<vector<int>>dp(nums1.size());
        int maxlen=INT_MIN;
        for(int i=0;i<nums1.size();i++)
        {
            dp[i].resize(nums2.size());
        }
        for(int i=0;i<nums1.size();i++)
        {
            dp[i][nums2.size()-1]=(nums1[i]==nums2[nums2.size()-1]?1:0);
            if(dp[i][nums2.size()-1]==1)maxlen=1;
        }
        for(int i=0;i<nums2.size();i++)
        {
            dp[nums1.size()-1][i]=(nums1[nums1.size()-1]==nums2[i]?1:0);
            if(dp[nums1.size()-1][i]==1)maxlen=1;
        }
        for(int i=nums1.size()-2;i>=0;i--)
        {
            for(int j=nums2.size()-2;j>=0;j--)
            {
                if(nums1[i]==nums2[j])
                {
                    dp[i][j]=dp[i+1][j+1]+1;
                    maxlen=max(maxlen,dp[i][j]);
                }
                else
                {
                    dp[i][j]=0;
                    maxlen=max(maxlen,dp[i][j]);
                }
            }
        }
        return maxlen;
    }
};

附:可降维优化为一维dp数组。(未尝试)

降维优化

dp[i][j] 只依赖上一行上一列的对角线的值,所以我们从右上角开始计算。

一维数组 dp , dp[j] 是以 A[i-1], B[j-1] 为末尾项的最长公共子数组的长度

相关推荐
一只码代码的章鱼1 小时前
5.4学习记录
学习·算法·动态规划
zhangxueyi1 小时前
Java实现归并排序算法
java·数据结构·算法
阿让啊2 小时前
C语言结构体内存对齐使用场景
c语言·开发语言·数据结构·单片机·算法
好想像大佬一样能够ak所有3 小时前
蓝桥杯-通电(最小生成树java)
java·数据结构·算法·蓝桥杯
JieJet3 小时前
[蓝桥杯 2025 省 B] 画展布置
数据结构·c++·算法·蓝桥杯
灏瀚星空3 小时前
基于Python的策略开发与回测:统计套利策略
开发语言·python·学习·算法·机器学习
福居路冥想的草莓3 小时前
翻转二叉树(简单)
数据结构·算法
啊阿狸不会拉杆4 小时前
人工智能数学基础(十)—— 图论
人工智能·python·数学·算法·图论
_Itachi__4 小时前
LeetCode 热题 100 189. 轮转数组
算法·leetcode·职场和发展
White_Can4 小时前
两数之和(暴力+哈希查找)
数据结构·算法·leetcode