一、题目描述
给两个整数数组 nums1 和 nums2 ,返回两个数组中 公共的 、长度最长的子数组的长度 。
输入格式
第一行输入一个正整数m,表示第一个数组nums1的数组长度。
第二行输入nums1数组中的元素。
第三行输入一个正整数n,表示第二个数组nums2的数组长度。
第四行输入nums2数组中的元素。
输出格式
最后输出一个数,表示最长重复子数组的长度。
示例如下:
输入:
5
1 2 3 2 1
5
3 2 1 4 7
输出:
3
解释:长度最长的公共子数组是 [3,2,1]
二、思路
按照动态规划的解题步骤:
-
确定dp数组的含义
首先是dp数组的含义,dp[i][j]表示的是以下标i-1结尾的数组nums1,以下标j-1结尾的数组nums2,最长重复子数组的长度是dp[i][j]。 -
确定递推公式
根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。即当nums1[i - 1] 和nums2[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1; -
do数组初始化
根据dp[i][j]的定义,dp[i][0] 和dp[0][j]都是没有意义的!因此dp[i][0]和dp[0][j]都初始化为0. -
确定dp数组的遍历顺序
无论是先遍历数组nums1或先遍历数组nums2都是可以的。 -
举例推导dp数组
三、C++代码
#include<bits/stdc++.h>
using namespace std;
//最长重复子数组
#define maxn 10010
int dp[maxn][maxn]; //dp[i][j]表示以下标i-1结尾的数组nums1和以下标j-1结尾的数组nums2的最长重复子数组的长度
int nums1[maxn] ;
int nums2[maxn];
int main(){
int m;
cin >> m;
for(int i = 1; i <= m; i ++) {
cin >> nums1[i];
}
int n;
cin>>n;
for(int i = 1; i <= n; i ++) {
cin >> nums2[i];
}
int result=0;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
dp[i][j]=1; //dp数组初始化
if(nums1[i-1]==nums2[j-1]){ //回退之前的状态
dp[i][j]=dp[i-1][j-1]+1;
}
if(dp[i][j]>result){
result=dp[i][j];
}
}
}
cout<<result;
}