最长公共子序列
学习记录自代码随想录
要点:1.!!dp数组定义不同结果不同,如果定义为dp数组dp[i][j]含义为以text1[i]结尾和以text2[j]结尾时最大的公共子序列长度则会超时(超时方法),定义为dp数组dp[i][j]含义为以长度为[0,i]的text1和长度为[0,j]的text2最大的公共子序列长度则可以通过,区别主要在递推公式上;
正确方法:
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.size(), n = text2.size();
// 1.dp数组dp[i][j]含义为以长度为[0,i]的text1和长度为[0,j]的text2最大的公共子序列长度
vector<vector<int>> dp(m, vector<int>(n, 0));
// 2.递推公式:for(int m = 0:i)
// for(int n = 0:j)
// if(text1[m] == text2[n]) dp[i][j] = max(dp[i][j], dp[m][n] + 1)
// 3.dp数组初始化
for(int i = 0; i < m; i++) if(text1[i] == text2[0]) dp[i][0] = 1;
for(int j = 0; j < n; j++) if(text1[0] == text2[j]) dp[0][j] = 1;
// 4.遍历顺序,正向遍历
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(text1[i] == text2[j] && i > 0 && j > 0){
dp[i][j] = dp[i-1][j-1] + 1;
}else if(i > 0 && j > 0){
dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
}else if(i > 0){
dp[i][j] = max(dp[i][j], dp[i-1][j]);
}else if(j > 0){
dp[i][j] = max(dp[i][j], dp[i][j-1]);
}
}
}
// 5.举例推导dp数组
return dp[m-1][n-1];
}
};
超时方法:
// 此种dp数组定义超时
class Solution {
public:
int longestCommonSubsequence(string text1, string text2) {
int m = text1.size(), n = text2.size();
// 1.dp数组dp[i][j]含义为以text1[i]结尾和以text2[j]结尾时最大的公共子序列长度
vector<vector<int>> dp(m, vector<int>(n, 0));
// 2.递推公式:for(int m = 0:i)
// for(int n = 0:j)
// if(text1[m] == text2[n]) dp[i][j] = max(dp[i][j], dp[m][n] + 1)
// 3.dp数组初始化
for(int i = 0; i < m; i++) if(text1[i] == text2[0]) dp[i][0] = 1;
for(int j = 0; j < n; j++) if(text1[0] == text2[j]) dp[0][j] = 1;
// 4.遍历顺序,正向遍历
int result = 0;
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
if(text1[i] == text2[j] && i > 0 && j > 0){
dp[i][j] = 1;
for(int p = 0; p < i; p++){
for(int q = 0; q < j; q++){
if(text1[p] == text2[q]) dp[i][j] = max(dp[i][j], dp[p][q]+1);
}
}
}
if(dp[i][j] > result) result = dp[i][j];
}
}
// 5.举例推导dp数组
return result;
}
};