什么是子序列
子序列和子串不一样,字串的求法很简单,用两层for循环即可得到。比如absv这个字符串,他的字串全部就是a,ab,abs,absv,b,bs,bsv,s,sv,v,和空
,但是它的子序列选择的方式更多,中间可以有空隔,比如asv
也是其子序列,所以求子序列,我们可以用递归,类似二叉树的求法,每一个位置都有两个状态,选与不选
代码
递归法
// str 固定参数
// 来到了str[index]字符,index是位置
// str[0..index-1]已经走过了!之前的决定,都在path上
// 之前的决定已经不能改变了,就是path
// str[index....]还能决定,之前已经确定,而后面还能自由选择的话,
// 把所有生成的子序列,放入到ans里去
public static void process1(char[] str, int index, List<String> ans, String path) {
if (index == str.length) {
ans.add(path);
return;
}
// 没有要index位置的字符
process1(str, index + 1, ans, path);
// 要了index位置的字符
process1(str, index + 1, ans, path + String.valueOf(str[index]));
}
动态规划版
这个力扣题可以说是十分经典了,求两个字符串的公共最长子序列,用动态规划是很好解决的,如果想用递归求二者所有子序列然后再比较的话,会超时(我试过了😂)。里面的题解也十分经典,是一位大佬做的,太牛逼了。
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int table[][] = new int[text1.length() + 1][text2.length() + 1];
for (int col=0; col<table[0].length; col++) {
table[0][col] = 0;
}
for (int row=0; row<table.length; row++) {
table[row][0] = 0;
}
for (int row=1; row<table.length;row++) {
char ch1 = text1.charAt(row-1);
for(int col=1; col<table[row].length; col++) {
char ch2 = text2.charAt(col-1);
if(ch1 == ch2) {
table[row][col] = table[row-1][col-1] + 1;
} else {
table[row][col] = Math.max(table[row-1][col], table[row][col-1]);
}
}
}
int[] lastRow = table[table.length-1];
return lastRow[lastRow.length-1];
}
}