文章目录
力扣算法学习day38-3
115-不同的子序列
题目
代码实现
class Solution {
// public int numDistinct(String s, String t) {
// // 直接想到的方法,超时了。 我用idea测试在本地测试了一下超时的那个案例,
// // 和下面正确解法的答案是一样的,这种方法应该可以,只是这道题会运行超时。
// char[] tList = t.toCharArray();
// char[] sList = s.toCharArray();
// // 如下,可以看出规律,类似深度遍历的思想。
// // r a b b b i t b a b g b a g
// // r 1 0 0 0 0 0 0 b 1 0 1 0 1 0 0
// // a 0 1 0 0 0 0 0 a 0 1 0 0 0 1 0
// // b 0 0 1 1 1 0 0 g 0 0 0 1 0 0 1 2 + 1 + 1 + 1
// // b 0 0 1 1 1 0 0
// // i 0 0 0 0 0 1 0
// // t 0 0 0 0 0 0 1 2+1+1
// boolean[][] dp = new boolean[tList.length][sList.length];
// for(int i = 0;i < tList.length;i++){
// for(int j = 0;j < sList.length;j++){
// if(tList[i] == sList[j]){
// dp[i][j] = true;
// }
// }
// }
// return sum(0,0,dp);
// }
// public int sum(int count,int index,boolean[][] dp){
// if(count == dp.length - 1){
// int sum = 0;
// for(int i = index;i < dp[count].length;i++){
// if(dp[count][i]){
// sum++;
// }
// }
// return sum;
// }
// int sum = 0;
// for(int i = index;i < dp[count].length;i++){
// if(dp[count][i]){
// sum += sum(count+1,i+1,dp);
// }
// }
// return sum;
// }
public int numDistinct(String s, String t) {
char[] tList = t.toCharArray();
char[] sList = s.toCharArray();
// dp
// dp[i][j]:表示以i-1结尾的s子序列中以j-1结尾的t的子序列出现的次数。
// 如果sList[i-1] == tList[j-1],那么有两种匹配情况
// 1.sList[i-1]元素用于匹配时的种数:
// 迭代公式:dp[i-1][j-1] 即i-2的s的子字符串和j-2结尾的t的子字符串的结果的个数即为匹配时的个数。
// 2.sList[i-1]不用于匹配,比如s 为 bagg,t 为bag,可以是第一个g匹配,也可以是第二个。种数:
// 迭代公式:dp[i-1][j]
// 所以如果sList[i-1] == tList[j-1],dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
// 如果sList[i-1] != tList[j-1],那么此时的元素不匹配,那么不用它,取上一个s的情况
// 故,迭代公式:dp[i][j] = dp[i-1][j];
int[][] dp = new int[sList.length+1][tList.length+1];
// 初始化
// 1.dp[0][i]需要初始化为0,因为s为空时,肯定合不出t。
// 2.dp[i][0]需要初始化为1.因为t为空时,s相当于全部减去后,都能匹配。其中应该包括dp[0][0]这个特殊位置。
// 注:通知也是为了迭代方程可以成立。
for(int i = 0;i < dp.length;i++){
dp[i][0] = 1;
}
// 遍历顺序的话都行,看懂迭代公式基本就懂了。 注:已测试,确实都可以。速度9ms
// for(int j = 1;j < dp[0].length;j++){
// for(int i = 1;i < dp.length;i++){
// if(sList[i-1] == tList[j-1]){
// dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
// } else{
// dp[i][j] = dp[i-1][j];
// }
// }
// }
// 不过这种遍历方式会更快。 速度 5ms
for(int i = 1;i < dp.length;i++){
for(int j = 1;j < dp[i].length;j++){
if(sList[i-1] == tList[j-1]){
dp[i][j] = dp[i-1][j-1] + dp[i-1][j];
} else{
dp[i][j] = dp[i-1][j];
}
}
}
return dp[sList.length][tList.length];
}
}