最长重复子数组

157 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情

一、题目

LeetCode 最长重复子数组

给两个整数数组 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

提示:

1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 100

二、题解

要求给定的两个数组中的公共子数组中最长的一个数组长度,子数组是公共的也就是两个数组中都存在的,并且子数组是连续的。

方法一

简单的可以通过遍历枚举数组的子数组,对比两个原数组,然后找到公共的子数组,最后记录下最长的子数组长度即可,但是可能超时。对此可以使用动态规划来解决,首先需要一个dp二维数组,用dp[i][j]表示数组nums1的前i个元素和数组nums2的前j个元素的公共子数组的长度,使用dp数组的大小就与nums1nums2两个数组的大小扩展加一。对于dp[i][j]来说如果nums1[i]的元素与nums2[j]的元素相同,说明这个元素可以添加组成公共子数组,所以长度可以在之前的最长公共子数组长度加一即dp[i][j] = dp[i - 1][j - 1] + 1;如果nums1[i]的元素与nums2[j]的元素不相同,那么就是说这个元素不能作为两个数组的公共子数组,所以这里的公共子数组长度就是0即dp[i][j] = 0。最后遍历过程中需要实时记录下dp[i][j]的最大长度,因为dp[i][j]记录的不是子数组的最大长度,而是公共子数组的长度,最终的就是公共子数组的最大长度。

三、代码

方法一 Java代码

class Solution {
    public int findLength(int[] nums1, int[] nums2) {
        int len1 = nums1.length;
        int len2 = nums2.length;
        int[][] dp = new int[len1 + 1][len2 + 1];
        int max = 0;
        for (int i = 1; i <= len1; i++) {
            for (int j = 1; j <= len2; j++) {
                dp[i][j] = nums1[i - 1] == nums2[j - 1] ? dp[i - 1][j - 1] + 1 : 0;
                max = Math.max(max, dp[i][j]);
            }
        }
        return max;
    }
}

时间复杂度:O(n^2),需要遍历枚举两个数组的元素来计算。

空间复杂度:O(n^2),动态规划需要使用一个二维数组。