leetcode 72:给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符
示例 1:
输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
假设,字符串a,长度为m:a[1].a[2].a[3].a[4]....a[m];字符串b,长度为n:b[1].b[2].b[3].b[4]....b[n];
用dp[i][j]表示长度i的字符串a转变为长度j的字符串b需要的操作数,dp[i][0]=i相当于不停的删除操作次数,dp[0][j]=j相当于不挺的插入操作次数
1.如果a[i]等于b[j],也即两个字符串的最后一位是一样的,那什么都不用做,直接躺赢了,问题转化为求a[1].a[2].a[3].a[4]...a[i-1]和b[1].b[2].b[3].b[4]....b[j-1]的最小操作数,
即dp[i][j]=dp[i-1][j-1],如果a[i-1]再等于b[j-1],则dp[i][j]=dp[i-2][j-2]
2.如果a[i]不等于b[j],要经过一次转变,变成一样的,有三种方式:替换、插入、删除,取三种方式的最小操作数
1)替换,将字符a[i]替换成b[j]的字符,需要的操作数是在原来的基础上加1,dp[i][j]=dp[i-1][j-1]+1;
2)插入(可以这么理解,a没有字符了,但b还有)将字符串a插入一个字符,让新插入的字符和b[j]相等,dp[i][j]=dp[i-1][j]+1;
3)删除,将字符串a删除一个字符,等价于将字符串b插入一个字符,让新插入的字符和a[i]相等,dp[i][j]=dp[i][j-1]+1;
......
层层递推,最终递推到dp[i][0]和dp[0][j],而这些初始状态是已知的,dp[i][0]=i,dp[0][j]=j
代码部分
1 public static int minDistance(String word1, String word2) { 2 if(word1==null||word2==null||word1.equals(word2)){ 3 return 0; 4 } 5 if("".equals(word1)){ 6 return word2.length(); 7 } 8 if("".equals(word2)){ 9 return word1.length(); 10 } 11 int[][] dp = new int[word1.length()+1][word2.length()+1]; 12 for(int i=1;i<=word1.length();i++) { 13 dp[i][0]=i; 14 } 15 for(int j=1;j<=word2.length();j++) { 16 dp[0][j]=j; 17 } 18 for(int i=1;i<=word1.length();i++) { 19 for(int j=1;j<=word2.length();j++) { 20 if(word1.charAt(i-1)==word2.charAt(j-1)){ 21 dp[i][j] = dp[i-1][j-1]; 22 }else{ 23 int temp = Math.min(dp[i][j-1], dp[i-1][j]); 24 dp[i][j] = Math.min(temp, dp[i-1][j-1])+1; 25 } 26 } 27 } 28 int minDistance = dp[word1.length()][word2.length()]; 29 System.out.println("最少操作数:"+minDistance); 30 return minDistance; 31 }
dp[i][0]=i,