问题描述
给两个整数数组 A
和 B
,返回两个数组中公共的、长度最长的子数组的长度。
示例:
输入:
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
问题思路
思路1:暴力法
对两个数组的起始位置的所有情况进行遍历,计算每种情况下的最长相同子数组的长度。
实现代码如下,空间复杂度O(1),时间复杂度O(n^3)。运行时间2740 ms。
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int n1 = nums1.length;
int n2 = nums2.length;
int out = 0;
for(int i = 0; i < n1; i++){
for(int j = 0; j < n2; j++){
int len = 0;
while(i + len < n1 && j + len < n2
&& nums1[i+len] == nums2[j+len]){
len++;
}
out = Integer.max(out, len);
}
}
return out;
}
}
思路2:动态规划法
观察思路1,发现有很多重复计算,考虑用动态规划减少重复计算次数。
进一步发现,从起始位置分别为 i, j 的最长相同子数组的长度 l(i,j) 满足:当 nums1[i] = nums2[j] 时,l(i,j) = l(i+1, j+1) + 1 ,否则 l(i, j) = 0。
由此递推式即可使用动态规划求解。
实现代码如下,空间复杂度O(mn),时间复杂度O(n^2)。运行时间46 ms。
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int n1 = nums1.length;
int n2 = nums2.length;
int out = 0;
for(int i = 0; i < n1; i++){
for(int j = 0; j < n2; j++){
int len = 0;
while(i + len < n1 && j + len < n2
&& nums1[i+len] == nums2[j+len]){
len++;
}
out = Integer.max(out, len);
}
}
return out;
}
}
思路3:滑动窗口法
其实比较得到最大长度,如果再加上一个条件:相同元素的下标位置一定相同,那么问题就变得非常简单,样例伪代码:
int len = 0;
int out = 0;
for(int i = 0; i < minleng; i++){
if(nums1[i] == nums2[i]){
len++;
out = Integer.max(out, len);
}else{
len = 0;
}
}
为了能满足这个条件,我们可以分别对某个数组的偏移量进行遍历,这样就得到所有对齐方式,然后对每个对齐方式进行计算,就可以得到最大长度。
实现代码如下,空间复杂度O(1),时间复杂度O((m+n)*min(m,n))。运行时间57 ms。
class Solution {
public int findLength(int[] nums1, int[] nums2) {
int n1 = nums1.length;
int n2 = nums2.length;
int out = 0;
for(int i = 0; i < n1; i++){
int len = sublength(nums1, nums2, i, 0, Integer.min(n2, n1 - i));
out = Integer.max(out, len);
}
for(int i = 0; i < n2; i++){
int len = sublength(nums1, nums2, 0, i, Integer.min(n1, n2 - i));
out = Integer.max(out, len);
}
return out;
}
public int sublength(int[] nums1, int[] nums2, int adda, int addb, int n){
int len = 0;
int out = 0;
for(int i = 0; i < n; i++){
if(nums1[i+adda] == nums2[i+addb]){
len++;
out = Integer.max(out, len);
}else{
len = 0;
}
}
return out;
}
}