本次题目
- 392 判断子序列
- 115 不同的子序列
- 583 两个字符串的删除操作
- 72 编辑距离
392 判断子序列
- DP:
- 定义dp数组dp[i][j]表示下标i-1(包括i-1)之前的字符串s和下标j-1(包括j-1)之前的字符串t,相同的子序列长度为dp[i][j];
- 递推公式如果s[i - 1] == t[j - 1],则dp[i][j] = dp[i - 1][j - 1] + 1,否则dp[i][j] = dp[i][j - 1];
- 初始化dp[0][j]和dp[i][0]为0;
- 遍历顺序正序;
- 举例。
class Solution {
public boolean isSubsequence(String s, String t) {
int s_leng = s.length();
int t_leng = t.length();
int[][] dp = new int[s_leng + 1][t_leng + 1];
for(int i = 1; i <= s_leng; i++){
for(int j = 1; j <= t_leng; 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];
}
}
}
if(dp[s_leng][t_leng] == s_leng) return true;
return false;
}
}
115 不同的子序列
- DP:
- 定义dp数组dp[i][j]表示下标i-1(包括i-1)之前的s子序列中出现下标j-1之前的t子序列的个数为dp[i][j];
- 递推公式如果s[i - 1] == t[j - 1],则dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j],否则dp[i][j] = dp[i - 1][j];
- 初始化dp[i][0] = 1,dp[0][j] = 0,dp[0][0] = 1;
- 遍历顺序正序;
- 举例。
class Solution {
public int numDistinct(String s, String t) {
int s_leng = s.length();
int t_leng = t.length();
if(t_leng == 0) return 1;
if(s_leng == 0) return 0;
int[][] dp = new int[s_leng + 1][t_leng + 1];
for(int i = 0; i <= s_leng; i++){
dp[i][0] = 1;
}
for(int i = 1; i <= s_leng; i++){
for(int j = 1; j <= t_leng; 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_leng][t_leng];
}
}
583 两个字符串的删除操作
- 对比上面115 不同的子序列,本题的两个字符串都可以删除。
- DP:
- 定义dp数组dp[i][j]表示下标i-1之前(包括i-1)的子字符串1和下标j-1之前(包括j-1)的子字符串相等时删除的最少次数;
- 递推公式如果word1[i - 1] == word2[j - 1],dp[i][j] = dp[i - 1][j - 1],否则dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1};
- 初始化dp[i][0] = i和dp[0][j] = j;
- 遍历顺序正序;
- 举例。
class Solution {
public int minDistance(String word1, String word2) {
int leng1 = word1.length();
int leng2 = word2.length();
int[][] dp = new int[leng1 + 1][leng2 + 1];
for(int i = 0; i <= leng1; i++){
dp[i][0] = i;
}
for(int j = 0; j <= leng2; j++){
dp[0][j] = j;
}
for(int i = 1; i <= leng1; i++){
for(int j = 1; j <= leng2; j++){
if(word1.charAt(i - 1) == word2.charAt(j - 1)){
dp[i][j] = dp[i - 1][j - 1];
}else{
dp[i][j] = Math.min(dp[i - 1][j] + 1, Math.min(dp[i][j - 1] + 1, dp[i - 1][j - 1] + 2));
}
}
}
return dp[leng1][leng2];
}
}
72 编辑距离
- 对比上题583 两个字符串的删除操作,本题不仅可以删除,还可以插入和替换,但是整体思路一致(插入其中一个字符串就相当于删除另一个字符串)。
- DP:
- 定义dp数组dp[i][j]表示下标i-1之前(包括i-1)的字符串1和下标j-1之前(包括j-1)的字符串2的最近编辑距离为dp[i][j];
- 递推公式如果word1[i - 1] == word2[j - 1],dp[i][j] = dp[i - 1][j - 1],否则dp[i][j] = min({dp[i - 1][j - 1], dp[i - 1][j], dp[i][j - 1]}) + 1;
- 初始化dp[i][0] = i和dp[0][j] = j;
- 遍历顺序正序;
- 举例。
class Solution {
public int minDistance(String word1, String word2) {
int leng1 = word1.length();
int leng2 = word2.length();
int[][] dp = new int[leng1 + 1][leng2 + 1];
for(int i = 0; i <= leng1; i++){
dp[i][0] = i;
}
for(int j = 0; j <= leng2; j++){
dp[0][j] = j;
}
for(int i = 1; i <= leng1; i++){
for(int j = 1; j <= leng2; j++){
if(word1.charAt(i - 1) == word2.charAt(j - 1)){
dp[i][j] = dp[i - 1][j - 1];
}else{
dp[i][j] = Math.min(dp[i - 1][j], Math.min(dp[i][j - 1], dp[i - 1][j - 1])) + 1;
}
}
}
return dp[leng1][leng2];
}
}