题目:
给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。
字符串的一个 子序列 是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,"ACE" 是 "ABCDE" 的一个子序列,而 "AEC" 不是)
题目数据保证答案符合 32 位带符号整数范围。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/distinct-subsequences
思路:
1. dp数组记录,此时分别以当前位置字符结尾时,子序列的数目!
2.当前字符相同,就可以将各自减一的个数(当前互相匹配) + 之前减一的s中已经包含的t的数目!
3.当前字符不同,只用将之前s减一时包含的此时t的个数挪下来即可!
需要初始化,每一行第一列的个数为1!
代码:
1)动态规划:时间复杂度为 O(N^2)
class Solution {
public int numDistinct(String s, String t) {
//还是进行子序列的比较,之前只是判断是否为子序列,此时要计算
int s1 = s.length();
int t1 = t.length();
int[][] dp = new int[s1 + 1][t1 + 1];
//初始化!将每一行的第一列初始化为1
for(int i = 0;i < s1;i++){
dp[i][0] = 1;
}
for(int i = 1;i <= s1;i++){
for(int j = 1;j <= t1;j++){
if(s.charAt(i - 1) == t.charAt(j - 1)){
//相同:将上挪下来 + 上左
dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
}
else{
//不相同:直接挪下来即可
dp[i][j] = dp[i - 1][j];
}
}
}
return dp[s1][t1];
}
}
2)使用滚动数组,优化空间复杂度
class Solution {
public int numDistinct(String s, String t) {
//还是进行子序列的比较,之前只是判断是否为子序列,此时要计算
int s1 = s.length();
int t1 = t.length();
//进行优化:一维数组;
//二维数组中看出来,只用到了上一行的内容;只用倒着进行更新,不会使用到当前行的内容即可
int[] dp = new int[t1 + 1];
dp[0] = 1;
for(int i = 1;i <= s1;i++){//更新的层:从上往下走
for(int j = t1;j > 0;j--){//更新列时:从后往前,防止覆盖
if(s.charAt(i - 1) == t.charAt(j - 1)){
dp[j] = dp[j] + dp[j - 1];
}
//其他情况时,不用进行更新
}
}
return dp[t1];
}
}