第一遍:暴力递归
不出所料,超时了。但是思路是没有错的。
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
char[] a = text1.toCharArray();
char[] b = text2.toCharArray();
return process(a, b, a.length - 1, b.length - 1);
}
// text1 : 0-i text:0-j 这个范围内的最长公共子序列的长度
int process(char[] text1, char[] text2, int i, int j){
if (i == 0 && j == 0) {
return text1[0] == text2[0] ? 1 : 0;
} else if (i == 0) {
if (text2[j] == text1[i]) {
return 1;
} else {
return process(text1, text2, i, j - 1);
}
} else if (j == 0) {
if (text1[i] == text2[j]) {
return 1;
} else {
return process(text1, text2, i - 1, j);
}
}
//下面是二者都不为0
//p1: 不以i结尾,不以j结尾 p2: 不以j结尾 p3:不以i结尾 p4:以i和j结尾
int p1 = process(text1, text2, i - 1, j - 1);
int p2 = process(text1, text2, i, j - 1);
int p3 = process(text1, text2, i - 1, j);
int p4 = 0;
if (text1[i] == text2[j]) {
p4 = p1 + 1;
}
return Math.max(Math.max(p3,p4), Math.max(p1,p2));
}
}
因为解法中存在大量的重复解,所以可以改为动态规划。变化的参数只有i和j,因此可以建立一个二维数组,长度为M*N(M为text1的长度,N为text2的长度)。
通过分析暴力递归过程可知,dp[i][j]依赖的位置有左上角元素,左面元素和上面元素。因此dp数组从左上往右下构建。
第二遍,改为动态规划
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
char[] a = text1.toCharArray();
char[] b = text2.toCharArray();
int alen = a.length;
int blen = b.length;
int[][] dp = new int[alen][blen];
if (a[0] == b[0]) dp[0][0] = 1;
for (int j = 1; j < blen; j++) {
dp[0][j] = a[0] == b[j] ? 1 : dp[0][j - 1];
}
for (int i = 1; i < alen; i++) {
dp[i][0] = b[0] == a[i] ? 1 : dp[i - 1][0];
}
for (int i = 1; i < alen; i++)
for (int j = 1; j < blen; j++) {
int p1 = dp[i-1][j - 1];
int p2 = dp[i - 1][j];
int p3 = dp[i][j - 1];
if (a[i] == b[j]) {
p1 = p1 + 1;
}
dp[i][j] = Math.max(p3, Math.max(p1,p2));
}
return dp[alen - 1][blen - 1];
}
}
运行结果: