最长重复子数组
给两个整数数组 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
滑动窗口
思路:
如下图,让两个数组“交错”在公共部分上找最长的相等子数组,这样比直接嵌套循环的去找两个相等子数组的复杂度要低;那么问题现在就变成了,如何让这两个数组“交错”?
可能因为我前期组织的还是比较凌乱的,当我看了答案,真的感叹真的非常的简洁清楚明朗,就是把其中的“遍历公共部分”单独抽离出来写成一个函数,然后后面的问题就是解决:怎么找到所有的“交错”的不同窗口,这一点就可以通过设置双指针来操作了;
上代码:
class Solution {
public:
int maxLength(vector<int>&nums1,vector<int>&nums2,int add1,int add2,int len){
int ret=0,k=0;
for(int i=0;i<len;i++){
if(nums1[add1+i]==nums2[add2+i]) k++;
else k=0;
ret=max(ret,k);
}
return ret;
}
int findLength(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size(); int m=nums2.size();
int ans=0;
for(int i=0;i<n;i++){//这里从不同的起点i开始就代表“交错”了
int len=min(m,n-i);
ans=max(ans,maxLength(nums1,nums2,i,0,len));
}
for(int i=0;i<m;i++){//相反的方向其实就是换另一个数组滑原来的方向
int len =min(n,m-i);
ans=max(ans,maxLength(nums1,nums2,0,i,len));
}
return ans;
}
};
- 时间复杂度: O((N+M)×min(N,M)),由于是交错,两个函数其实遍历分别只持续了O(N+M)和
O(N,N),而两个函数嵌套,因此最终时间复杂度为两者乘积. - 空间复杂度: O(1).没有用到额外空间.