动态规划
392.判断子序列
解题思路:
类似于这种两个字符串比较,替换,删除的题目都可以用二维dp解决
- 定义
dp数组含义:dp[i][j]代表s以i-1结尾,m以j-1结尾的最长公共子序列 - 初始化: 当
word1为空时, 两个字符串相同的最少操作次数是word2的长度, 即删除所有的word2 - 双重for循环比较:
- 两个字符相等时: 最长公共子序列长度就是
dp[i-1[j-1] + 1 - 当不相等时: 最长公共子序列长度 =
Math.max(dp[i-1][j], dp[i][j-1])
- 最后判断最长公共子序列长度是否等于
s的长度即可
代码:
class Solution {
// 判断子序列本质: 找最长公共子序列长度是否等于子序列长度
public boolean isSubsequence(String s, String t) {
int m = s.length(), n = t.length();
// 动态规划---找最长公共子序列
int[][] dp = new int[m+1][n+1];
for(int i=1; i<=m; i++){
for(int j=1; j<=n; j++){
if(s.charAt(i-1) == t.charAt(j-1)){
dp[i][j] = dp[i-1][j-1] + 1;
}else{
dp[i][j] = Math.max(dp[i][j-1], dp[i-1][j]);
}
}
}
// 若最长公共子序列长度 = m, 则代表s是t的子序列
return dp[m][n] == m;
}
}
115.不同的子序列
解题思路:二维dp
- 定义dp数组含义:
s以i-1结尾,t以j-1结尾的s的子序列中t出现的个数 - 若两个字符相等: 则当前dp[i][j] 可以使用当前元素来匹配, 或者不使用当前元素来匹配
- 若两个字符不相等: 则不能使用当前元素来匹配
代码:
class Solution {
// 动态规划
public int numDistinct(String s, String t) {
int m = s.length(), n = t.length();
// dp 数组含义: 定义s以i结尾, t以j结尾的s中t的不同子序列个数
int[][] dp = new int[m+1][n+1];
// 初始化
for (int i = 0; i <= m; i++) dp[i][0] = 1;
for(int i=1; i<=m; i++){
for(int j=1; j<=n; 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[m][n];
}
}