力扣392.判断子序列
题目链接:https://leetcode.cn/problems/is-subsequence/
思路
本题和最长公共子序列基本上类似,求得s和t的最长公共子序列,再判断最长公共子序列的长度是否等于s的长度即可。
还有一点不一样的是,在递推公式中,当s.charAt(i-1) != t.charAt(j-1)
时,只需要回退j,也就是说只需要回退字符串t,因为是要判断s是不是t的子序列。
完整代码
class Solution {
public boolean isSubsequence(String s, String t) {
int[][] dp = new int[s.length()+1][t.length()+1];
for (int i = 1; i <= s.length(); i++) {
for (int j = 1; j <= t.length(); j++) {
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = dp[i][j-1];
}
}
}
int res = dp[s.length()][t.length()];
if(res == s.length()){
return true;
}else {
return false;
}
}
}
力扣115.不同的子序列
题目链接:https://leetcode.cn/problems/distinct-subsequences/
思路
这道题对于我来说真的有点难度,有点难理解,可能是之前这一系列就没有完全吃透
dp数组的含义
dp[i][j]:以i-1为结尾的字符串s包含以j-1为结尾的字符串t的个数
递推公式
(1)当s.charAt(i-1) == t.charAt(j-1)
时,例如s=bagg,t=bag,s[3]==t[2],有两种情况:考虑当前匹配的字符;不考虑当前的字符,那么s回退,t不可以回退,就是比较s[2]和t[2],还是相等的。所以需要将两种情况相加
(2)不相等时,回退s,不回退t
初始化
由于递推公式的需要,需要初始化dp[i][0],dp[0][j],还有一种特殊情况dp[0][0]
根据dp的定义:
(1)dp[i][0]表示以i-1为结尾的字符串s包含以-1为结尾的字符串t的个数,就是拿s去匹配空字符串,匹配个数为1
(2)dp[0][j]表示以-1为结尾的字符串s包含以j-1为结尾的字符串t的个数,就是拿空字符串去匹配非空,肯定是匹配不上的,所以为0
(3)dp[0][0]表示以-1为结尾的字符串s包含以-1为结尾的字符串t的个数,就是拿空字符串去匹配空字符串,匹配个数为1
遍历顺序
从前向后
打印数组
完整代码
class Solution {
public int numDistinct(String s, String t) {
int[][] dp = new int[s.length()+1][t.length()+1];
for (int j = 1; j < t.length(); j++) {
dp[0][j] = 0;
}
for (int i = 0; i < s.length(); i++) {
dp[i][0] = 1;
}
for (int i = 1; i <= s.length(); i++) {
for (int j = 1; j <= t.length(); 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[s.length()][t.length()];
}
}