这里LeetCode上两道题目,难度为中等和困难。
字符串有三种编辑操作:插入一个字符、删除一个字符或者替换一个字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。
示例 1:
输入:
first = "pale"
second = "ple"
输出: True
示例 2:
输入:
first = "pales"
second = "pal"
输出: False
双指针写法
public boolean oneEditAway(String first, String second) {
// 获取两个字符串的长度差,超过1的肯定不满足条件直接返回false
int len = first.length() - second.length();
if(len < -1 || len > 1){
return false;
}
// 定义差别值
int count = 0;
for (int i = 0, j = 0; i < first.length()&& j < second.length(); i++,j++) {
// 如果出现字符不相等的情况
if(first.charAt(i) != second.charAt(j)){
if(len == 1){
// 如果first比较长,那么j指针后退一位,相当于空出当前位置交给下一次比较
j--;
}else if(len == -1){
// 如果second比较长,那么i指针后退一位,相当于空出当前位置交给下一次比较
i--;
}
// 差别值+1
count++;
}
// 差别值>1返回false
if(count >1){
return false;
}
}
return true;
}
给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
示例 1:
输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:
输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')
动态规划解法:
public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
// n m 中有为0的情况
if (n*m==0) {
return n+m;
}
// 初始化状态数组
int[][] dp = new int[n+1][m+1];
// 边界初始化,每移动一个位置相当于一次操作
for (int i = 0; i < n + 1; i++) {
dp[i][0] = i;
}
for (int i = 0; i < m + 1; i++) {
dp[0][i] = i;
}
// 从1开始代表第一个字符,故字符的位置为i-1
for (int i = 1; i < n + 1; i++) {
for (int j = 1; j < m + 1; j++) {
// ex : {"*b","*c"} 当前字符为b c
// ex : {"*b","*c"} 对word1进行删除b
// ex : {"*,*c"} 删除b后,需要判断i-1和j
int delete = dp[i-1][j]+1;
// ex : {"*b","*c"} 当前字符为b c
// ex : {"*bc","*c"} 对word1进行插入c
// ex : {"*b,*"} 插入后c可以相当于消除,那么只需要判断i和j-1即可
int insert = dp[i][j-1]+1;
// ex : {"*b","*c"} 当前字符为b c
// ex : {"*c","*c"} 对word1进行替换c
// ex : {"*,*"} 替换c后,需要判断i-1和j-1
int replace = dp[i-1][j-1];
// 如果当前字符相等,则跳过,不相等则操作+1
if (word1.charAt(i-1)!=word2.charAt(j-1)) {
replace += 1;
}
dp[i][j] = Math.min(insert,Math.min(delete,replace));
}
}
return dp[n][m];
}
递归加状态存储写法:
public int minDistance(String word1, String word2) {
int n = word1.length();
int m = word2.length();
// 初始化状态数组
int[][] dp = new int[n+1][m+1];
return minDistanceRecursive(word1.toCharArray(),word2.toCharArray(),n,m,dp);
}
private int minDistanceRecursive(char[] word1, char[] word2, int n, int m, int[][] dp) {
int count;
// 如果n m 位置已经有值,直接返回
if (dp[n][m]!=0) {
return dp[n][m];
}
// n m 中有数值为0的
if (n*m==0) {
count = n+m;
} else if (word1[n-1]==word2[m-1]) {
// n m 位置的值相等,直接跳过
count = minDistanceRecursive(word1,word2,n-1,m-1,dp);
} else {
// 不等,执行插入、删除、替换三种操作,取最小的值+1(当前操作值)
int insert = minDistanceRecursive(word1,word2,n,m-1,dp);
int delete = minDistanceRecursive(word1,word2,n-1,m,dp);
int replace = minDistanceRecursive(word1,word2,n-1,m-1,dp);
count = Math.min(insert,Math.min(delete,replace))+1;
}
// 状态存储
dp[n][m] = count;
return count;
}