题目来源:718:https://leetcode.com/problems/maximum-length-of-repeated-subarray/description/
动态规划基础训练。
718. Maximum Length of Repeated Subarray
题目大意
求出数组A、B的最大公共子数组的长度。
例
Input:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
Output: 3
Explanation:
The repeated subarray with maximum length is [3, 2, 1].
思路
其实本质是求出字符串A、B的最大公共字串的长度。
和编辑距离思路差不多,甚至还要更简单一些。
可考虑矩阵法。(列表)
矩阵法
(1)创建一个(sizeA+1)*(sizeB+1)的矩阵m,用于记录以元素m[i][j]结尾的最大公共子数组的长度,初始化为0;
(2)若数组A中第i个元素A[i-1]与数组B中第j个元素B[j-1]相等,m[i][j] = m[i-1][j-1]+1;
(3)矩阵中最大的数即数组A、B的最大公共子数组的长度,最长的对角线所对应元素即数组A、B的最大公共子数组。
以题目大意中例子为例,画出矩阵
3 | 2 | 1 | 4 | 7 | ||
---|---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 | |
1 | 0 | 0 | 0 | 1 | 0 | 0 |
2 | 0 | 0 | 1 | 0 | 0 | 0 |
3 | 0 | 1 | 0 | 0 | 0 | 0 |
2 | 0 | 0 | 2 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 3 | 0 | 0 |
数组A、B的最大公共子数组的长度即为m[5][3] = 3,最大公共子数组为{3,2,1}。
为什么要这么做呢,我们分析一下状态转移式。
状态转移式
若数组A中第i个元素A[i-1]与数组B中第j个元素B[j-1]相等,则考虑数组A中第i-1个元素A[i-2]与数组B中第j-1个元素B[j-2]是否相等。
不管前面的元素是否相等,以该相同元素结尾的最大公共子数组的长度都应在以前面元素结尾的最大公共子数组的长度的基础上+1,所以有以下状态转移式:
m[i][j] = m[i-1][j-1]+1;
解题代码
class Solution {
public:
int findLength(vector<int>& A, vector<int>& B) {
int sizeA = A.size();
int sizeB = B.size();
int max = 0;
int matrix[sizeA+1][sizeB+1] = {0};
for (int i = 0; i < sizeA+1; i++) matrix[i][0] = 0;
for (int i = 0; i < sizeB+1; i++) matrix[0][i] = 0;
for (int i = 1; i < sizeA+1; i++) {
for (int j = 1; j < sizeB+1; j++) {
if (A[i-1] == B[j-1]) matrix[i][j] = matrix[i-1][j-1]+1;
else matrix[i][j] = 0;
if (matrix[i][j] > max) max = matrix[i][j];
}
}
// for (int i = 1; i < sizeA+1; i++) {
// for (int j = 1; j < sizeA+1; j++) {
// cout << matrix[i][j] << " ";
// }
// cout << endl;
// }
return max;
}
};
时间复杂度
O(n^2)