LeetCode原题
- 算法
- 1.动态规划:dp[i][j]表示str1[0,i-1]和str2[0,j-1]的最长公共子序列
- 2.初始状态:dp[x][0] = 0, dp[0][x] = 0
- 3.过渡公式:
- 如果str1[i]==str2[j], dp[i][j] = dp[i-1][j-1] + 1;
- 如果str1[i]!=str2[j], dp[i][j] = MAX(dp[i-1][j], dp[i][j-1]);
public int longestCommonSubsequence(String text1, String text2) {
int[][] dp = new int[text1.length()+1][text2.length()+1];
for (int i = 1; i <= text1.length(); i++) {
for (int j = 1; j <= text2.length(); j++) {
if (text1.charAt(i-1) == text2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
return dp[text1.length()][text2.length()];
}
- 算法
- 1.空间优化
- 2.考虑每轮外层循环更新dp数组需要那些值来使用辅助变量
public int longestCommonSubsequence(String text1, String text2) {
int[] dp = new int[text2.length()+1];
for (int i = 1; i <= text1.length(); i++) {
int prev = dp[0], curr = dp[1];
for (int j = 1; j <= text2.length(); j++) {
if (text1.charAt(i-1) == text2.charAt(j-1)) {
dp[j] = prev + 1;
} else {
dp[j] = Math.max(curr, dp[j-1]);
}
if (j < text2.length()) {
prev = curr;
curr = dp[j+1];
}
}
}
return dp[text2.length()];
}
牛客本题
- 算法
- 1.动态规划的过程中保存结果:伴随dp数组的StringDp数组跟随变化
- 2.避免内存超限,这里使用优化后的空间复杂度来计算
public String LCS(String text1, String text2) {
String[] stringDp = new String[text2.length()+1];
for (int i = 0; i < stringDp.length; i++) {
stringDp[i] = new String();
}
int[] dp = new int[text2.length()+1];
for (int i = 1; i <= text1.length(); i++) {
int prev = dp[0], curr = dp[1];
String stringPrev = stringDp[0], stringCurr = stringDp[1];
for (int j = 1; j <= text2.length(); j++) {
if (text1.charAt(i-1) == text2.charAt(j-1)) {
dp[j] = prev + 1;
stringDp[j] = stringPrev + text2.substring(j-1, j);
} else {
dp[j] = Math.max(curr, dp[j-1]);
if (curr > dp[j-1]) {
dp[j] = curr;
stringDp[j] = stringCurr;
} else {
dp[j] = dp[j-1];
stringDp[j] = stringDp[j-1];
}
}
if (j < text2.length()) {
prev = curr;
curr = dp[j+1];
stringPrev = stringCurr;
stringCurr = stringDp[j+1];
}
}
}
return stringDp[text2.length()];
}
public String LCS(String text1, String text2) {
int length1 = text1.length(), length2 = text2.length();
int[][] dp = new int[length1+1][length2+1];
for (int i = 1; i <= text1.length(); i++) {
for (int j = 1; j <= text2.length(); j++) {
if (text1.charAt(i-1) == text2.charAt(j-1)) {
dp[i][j] = dp[i-1][j-1] + 1;
} else {
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]);
}
}
}
StringBuilder result = new StringBuilder();
int i = length1, j = length2;
while (i > 0 && j > 0) {
if (text1.charAt(i-1) == text2.charAt(j-1)) {
result.append(text1.charAt(i-1));
i--;
j--;
} else {
if (dp[i][j-1] > dp[i-1][j]) {
j--;
} else {
i--;
}
}
}
return result.reverse().toString();
}