力扣算法学习day39-2
583-两个字符串的删除操作
代码实现-完全版-补上上午的dp解法2
class Solution {
// 方法一:dp,求两个字符串的最长公共子序列的长度,然后两个分别长度减去它相加即为答案。速度:4ms
// public int minDistance(String word1, String word2) {
// char[] char1 = word1.toCharArray();
// char[] char2 = word2.toCharArray();
// int[][] dp = new int[char1.length+1][char2.length+1];
// for(int i = 1;i < dp.length;i++){
// for(int j = 1;j < dp[i].length;j++){
// if(char1[i-1] == char2[j-1]){
// dp[i][j] = dp[i-1][j-1] + 1;
// } else{
// dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]);
// }
// }
// }
// int length = dp[char1.length][char2.length];
// int result = char1.length + char2.length - 2 * length;
// return result;
// }
// 方法二:dp,通过减去的思路来求 速度 4ms
public int minDistance(String word1, String word2) {
char[] char1 = word1.toCharArray();
char[] char2 = word2.toCharArray();
// 思路:dp[i][j]:为i-1结尾char1子字符串和j-1结尾的char2子字符串的相同需要的最小步数。
// 1.char1[i-1] == char2[j-1]:当前元素相同,不需要删除,那么删除情况取i-2结尾char1子字符串
// 和j-2结尾char2子字符串的删除情况即可。
// 迭代公式:dp[i][j] = dp[i-1][j-1];
// 2.char1[i-1] != char2[j-1]:说明需要删除元素有三种种情况如下
// (1) 删除char1[i-1]:取dp[i-1][j] + 1(删除的这个元素).
// (2) 删除char2[j-1]:取dp[i][j-1] + 1(删除的这个元素).
// (3) 两个都删除,但是可以分析得出,这种情况实际上是被上两种包含了。
// 故迭代公式为取它们是最小情况:dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1);
int[][] dp = new int[char1.length+1][char2.length+1];
// 初始化
// 1.dp[i][0]: 需要以i-1结尾的char1子字符串删除所有才能和空字符串相同所以dp[i][0] = i;
// 2.dp[0][j]: 同理可得dp[0][j] = j; 注:这里dp[0][0]其实就不需要删除,被两种情况都包含。
for(int i = 0;i < dp.length;i++){
dp[i][0] = i;
}
for(int j = 0;j < dp[0].length;j++){
dp[0][j] = j;
}
for(int i = 1;i < dp.length;i++){
for(int j = 1;j < dp[i].length;j++){
if(char1[i-1] == char2[j-1]){
dp[i][j] = dp[i-1][j-1];
} else{
dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1);
}
}
}
return dp[char1.length][char2.length];
}
}
72-编辑距离
题目
代码实现
class Solution {
public int minDistance(String word1, String word2) {
char[] char1 = word1.toCharArray();
char[] char2 = word2.toCharArray();
// dp:速度 3-4ms(提交了两次)
// 1.解法分析:首先这道题是连个字符串的问题,所求的东西是一个最小的值,不需要具体的情况输出,所以
// 不考虑回溯,那么多半是dp思路,而两个字符串的问题,且两个字符串的长度小于10的2次方,那多考虑
// 多半是二维dp数组来解决。
// 2.题目分析:本题类似于删除情况的拓展,即583问题的拓展,在583的情况还要考虑替换,插入这两种情况。
// 3.定义:dp[i][j]:不妨还是定义为以i-1结尾的char1子字符串和j-1结尾的子字符串变为相同需要最好操作数。
// 注意:这里操作数有插入、删除、替换三种情况。
// 4.迭代公式确定:
// (1)如果char1[i-1] == char2[j-1]:说明当前这两个字符是相同的,所以直接等于以i-2结尾的char1子字符串和
// 以j-2结尾的char2结尾的子字符串的最小操作数即可,即:dp[i][j] = dp[i-1][j-1];
//
// (2)如果char1[i-1] != char2[j-1],说明当前这两个字符不相同,所以需要操作,那么首先有三种操作可以使用。
// 删除操作:删除char1[i-1],相当于取i-2结尾的char1子字符串和j-1结尾的子字符串的最小操作情况+1(加上这个删除操作)。
// 即:dp[i-1][j]+1.
//
// 插入操作:插入新元素,新元素等于char2的第j-1个元素。这里插入需要理解,char1插入新元素,其实与char2删除j-1这个
// 元素等效,比如 char1为 a ,char2为ab,那么对于char1的操作为插入b,对于char2的操作为删除b,所以一样
// 所以,插入插入操作可以转换成char2删除j-1元素。同理,可得:dp[i][j-1]+1.
//
// 替换操作:替换操作相当于i-2结尾的char1和j-2结尾的char2子字符串的最小操作情况加上1,即加上将char1中第i-1个元素
// 替换成char2中第j-1个元素这个替换操作。即dp[i-1][j-1]+1
//
// 最终迭代公式(在三种情况中取最小):dp[i][j] = Math.min(Math.min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]) + 1;
int[][] dp = new int[char1.length+1][char2.length+1];
// 初始化
// 1.dp[i][0]: 需要以i-1结尾的char1子字符串删除所有才能和空字符串相同所以dp[i][0] = i;
// 2.dp[0][j]: 同理可得dp[0][j] = j;
for(int i = 0;i < dp.length;i++){
dp[i][0] = i;
}
for(int j = 0;j < dp[0].length;j++){
dp[0][j] = j;
}
for(int i = 1;i < dp.length;i++){
for(int j = 1;j < dp[i].length;j++){
if(char1[i-1] == char2[j-1]){
dp[i][j] = dp[i-1][j-1];
} else{
dp[i][j] = Math.min(Math.min(dp[i-1][j],dp[i][j-1]),dp[i-1][j-1]) + 1;
}
}
}
return dp[char1.length][char2.length];
}
}