本文主要是介绍2021-12-29 718. 最长重复子数组(动态规划),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
注:
题目:
给两个整数数组 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
题解:
确定dp数组(dp table)以及下标的含义
dp[i][j] :以下标i - 1为结尾的A,和以下标j - 1为结尾的B,最长重复子数组长度为dp[i][j]。
确定递推公式
根据dp[i][j]的定义,dp[i][j]的状态只能由dp[i - 1][j - 1]推导出来。
即当A[i - 1] 和B[j - 1]相等的时候,dp[i][j] = dp[i - 1][j - 1] + 1;
根据递推公式可以看出,遍历i 和 j 要从1开始!
dp数组如何初始化
根据dp[i][j]的定义,dp[i][0] 和dp[0][j]其实都是没有意义的!
但dp[i][0] 和dp[0][j]要初始值,因为 为了方便递归公式dp[i][j] = dp[i - 1][j - 1] + 1;
所以dp[i][0] 和dp[0][j]初始化为0。
举个例子A[0]如果和B[0]相同的话,dp[1][1] = dp[0][0] + 1,只有dp[0][0]初始为0,正好符合递推公式逐步累加起来。
确定遍历顺序
外层for循环遍历A,内层for循环遍历B。
同时题目要求长度最长的子数组的长度。所以在遍历的时候顺便把dp[i][j]的最大值记录下来。
复杂度分析
时间复杂度:O(n × m),n 为A长度,m为B长度
空间复杂度:O(n × m)
class Solution {
public:int findLength(vector<int>& nums1, vector<int>& nums2) {int size1=nums1.size();int size2=nums2.size();int result=0;if(size1==0||size2==0){return 0;}vector<vector<int>> dp(size1+1,vector<int>(size2+1));//以下标i-1为结尾的A,和以下标j-1为结尾的B,最长重复子数组长度为dp[i][j]for(int i=1;i<=size1;i++){for(int j=1;j<=size2;j++){if(nums1[i-1]==nums2[j-1]){dp[i][j]=dp[i-1][j-1]+1;}result=max(result,dp[i][j]);}}return result;}
};
这篇关于2021-12-29 718. 最长重复子数组(动态规划)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!