[力扣 718] [leetcode 718] 最长重复子数组 2021.9.25
题目描述
给两个整数数组 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-length-of-repeated-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
与 583 类似
但是这个题目要求子序列是连续的。如果不连续则不能算。
dp递推公式中的意义
本题dp table意义
dp[i][j] 代表以终点为nums1[i] nums2[j]时候的最长公共子序列长度。
所以要以不同的i,j 为终点求一个最大的长度。
如果dp[i][j] 的意义为 nums[0-i] nums2[0-j] 时的最长公共子序列长度
那是否是意味着 dp[nums1.size()][nums2.size()] 就是我们要求的结果?
那是否有
if value_equal:
XXX
else:
dp[i][j] = std::max(dp[i][j-1], dp[i-1][j]);
这样的代码呢?🤔
583题的相似性
如果像 583 那样
if text1[i] == text2[j]:
dp[i][j] = dp[i-1][j-1] + 1
else:
dp[i][j] = max(dp[i-1][j], dp[i][j-1])
则代表着,不论什么情况下都可以使用前面的值进行状态转移。(使用前面的状态进行推导)
而使用前面的状态推导是有条件的, 那就是此次推导与前面的值有关
那当 nums1[j] != nums2[j] 的时候,就与前面的值没有关系了🤔
但是此题目有:
- 如果相等,则可以使用前面的值
- 如果不相等,则不能使用前面的值。所以在这里dp[i][j] = 0
主要还是要想明白dp table的意义。
代码
class Solution {
public:
int findLength(vector<int>& nums1, vector<int>& nums2) {
std::vector<std::vector<int>> dp(nums1.size() + 1, std::vector<int>(nums2.size() + 1, 0));
for (int i = 1; i < nums1.size() + 1; i++) {
for (int j = 1; j < nums2.size() + 1; j++) {
if (nums1[i - 1] == nums2[j - 1]) {
// 如果相等,看前面的值是否相等。
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
// 如果不相等,则本i,j的最长公共序列为0
dp[i][j] = 0;
}
}
}
int max_val = 0;
for (int i = 0; i <= nums1.size(); i++) {
for (int j = 0; j <= nums2.size(); j++) {
max_val = std::max(max_val, dp[i][j]);
}
}
return max_val;
}
};

浙公网安备 33010602011771号