持续创作,加速成长!这是我参与「掘金日新计划 · 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数组的大小就与nums1、nums2两个数组的大小扩展加一。对于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),动态规划需要使用一个二维数组。