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

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

. - 力扣(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. TCP协议是安全的吗?

    2024-03-27 16:52:05       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-27 16:52:05       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-27 16:52:05       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-27 16:52:05       18 阅读

热门阅读

  1. 【Linux之·指令gnome-terminal】

    2024-03-27 16:52:05       19 阅读
  2. js实现base64转字符串

    2024-03-27 16:52:05       19 阅读
  3. Unity 中的特殊文件

    2024-03-27 16:52:05       15 阅读
  4. 掌握Qt开发技能:打造跨平台应用的利器

    2024-03-27 16:52:05       18 阅读
  5. 力扣4寻找两个正序数组的中位数

    2024-03-27 16:52:05       14 阅读
  6. C语言 如何定义和使用结构体?

    2024-03-27 16:52:05       16 阅读
  7. 前后端实时数据通信

    2024-03-27 16:52:05       16 阅读
  8. a链接下载zip压缩包

    2024-03-27 16:52:05       18 阅读
  9. 08 React 使用uuid示例

    2024-03-27 16:52:05       15 阅读