这是我参与2022首次更文挑战的第17天,活动详情查看:2022首次更文挑战」。
718. 最长重复子数组
题目描述
给两个整数数组 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
动态规划解析
/**
* @brief 动态规划
* 1、确定dp数组以及下标的含义
* dp[i][j] : 表示以下标 i-1 为结尾的nums1 和 以下标j-1为结尾的nums2,最长重复子数组长度为 dp[i][j]
* 2、确定递推公式
* dp[i][j]只能由dp[i-1][j-1]推导出来
* 当 nums1[i-1]和nums2[j-1]相等的时候,dp[i][j] = dp[i-1][j-1]+1
*
* 3、初始化dp数组
* dp[i][0]与dp[0][j]都无意义,所以都初始为0
* 4、确定遍历的顺序
* 下标从1开始。两层for循环进行遍历
*
*/
动态规划代码
class Solution
{
public:
int findLength(vector<int> &nums1, vector<int> &nums2)
{
// 定义dp数组
vector<vector<int>> dp(nums1.size() + 1, vector<int>(nums2.size() + 1, 0));
int result = 0;
for (int i = 1; i <= nums1.size(); i++)
{
for (int j = 1; j <= nums2.size(); j++)
{
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];
}
}
}
return result;
}
};
滑动数组解析
/**
* @brief 滑动数组
* 可以看出dp[i][j]都是由dp[i - 1][j - 1]推出。那么压缩为一维数组,也就是dp[j]都是由dp[j - 1]推出。
* 也就是相当于可以把上一层dp[i - 1][j]拷贝到下一层dp[i][j]来继续用。
* 此时遍历nums2数组的时候,就要从后向前遍历,这样避免重复覆盖。
*/
滑动数组代码
class Solution
{
public:
int findLength(vector<int> &nums1, vector<int> &nums2)
{
vector<int> dp(nums2.size() + 1, 0);
int result = 0;
for (int i = 1; i <= nums1.size(); i++)
{
for (int j = nums2.size(); j > 0; j--)
{
if (nums1[i - 1] == nums2[j - 1])
{
dp[j] = dp[j - 1] + 1;
}
else
{
dp[j] = 0;
}
if (dp[j] > result)
{
result = dp[j];
}
}
}
return result;
}
};