#leetcode#Edit Distance

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

You have the following 3 operations permitted on a word:

a) Insert a character
b) Delete a character
c) Replace a character

===========

毫无思路,学习code ganker

http://codeganker.blogspot.com/2014/04/edit-distance-leetcode.html#comment-form

以及Discuss   https://leetcode.com/discuss/17997/my-accepted-java-solution

This is a very interesting question and I found a youtube video that helps a lot. Basically the idea is to build up the solution step by step and keep track of the previous optimal solution in a 2D array. In this 2D array dp, dp[i][j] means the operation needed to transform word1(0, i) to word2(0,j).

There can be three conditions:

1, word1[i] == word2[j] : then no operation needed. dp[i][j] == dp[i-1][j-1]

2, Do one operation on word1[i-1][j]. dp[i][j] = dp[i-1][j] + 1

3, Do one operation on word2[i][j-1]. dp[i][j] = dp[i][j-1] + 1

4, 补充一点 replace操作: dp[i][j] = dp[i - 1][j - 1] + 1

for 2 and 3, the reason it works is that we know the optimal ways to transfrom word1(0,i) to word2(0,j-1) and word1(0,i-1) to word(0,j) ( Delete ("abc" to "ab") or Insert ("ab" to "abc") ). Now all we need to one more operation.


===========

具体到代码实现又出现了新的问题:为什么二维数组 dp[i][j]的最左边一列和最上面一行要初始化成对应 i 和 j 的值呢?

比如 dp[i][0], 表示的意思是从word2长度为0时要变到位置i的word1, 则需要word1的当前长度步,也就是i的值。

时间复杂度双层循环 O(m * n)

public class Solution {
    public int minDistance(String word1, String word2) {
        
        if(word1.length() == 0){
            return word2.length();
        }
        if(word2.length() == 0){
            return word1.length();
        }
        
        int[][] dp = new int[word1.length() + 1][word2.length() + 1];
        for(int i = 0; i <= word1.length(); i++){
            dp[i][0] = i;
        }
        for(int j = 0; j <= word2.length(); j++){
            dp[0][j] = j;
        }
        
        for(int i = 1; i <= word1.length(); i++){
            for(int j = 1; j <= word2.length(); j++){
                if(word1.charAt(i - 1) == word2.charAt(j - 1)){
                    dp[i][j] = dp[i - 1][j - 1];
                }else{
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i - 1][j - 1]), dp[i][j - 1]) + 1;
                }
            }
        }
        
        return dp[word1.length()][word2.length()];
    }
}

接下来研究一下如何省空间,


dp[i][j]需要用到 i -1 和 j - 1的数据,所以只要维护前面一行的结果就ok了

每循环到新的一行, 初始化第一个元素, 即上面解法中设置第一列

public class Solution {
    public int minDistance(String word1, String word2) {
        
        if(word1.length() == 0){
            return word2.length();
        }
        if(word2.length() == 0){
            return word1.length();
        }
        
        int[] dp = new int[word2.length() + 1];
        for(int i = 0; i <= word2.length(); i++){  // word2.length() is the column number
            dp[i] = i;                              //initial the first row
        }
        
        for(int i = 1; i <= word1.length(); i++){  // word1.length() is the row number
            int[] newDp = new int[word2.length() + 1];
            newDp[0] = i;                           // initial the first column
            for(int j = 1; j <= word2.length(); j++){
                if(word1.charAt(i - 1) == word2.charAt(j - 1)){
                    newDp[j] = dp[j - 1];
                }else{
                    newDp[j] = Math.min(Math.min(dp[j], dp[j - 1]), newDp[j - 1]) + 1;
                }
            }
            dp = newDp;
        }
        return dp[word2.length()];
    }
}
这样空间复杂度是O(n), n为word2的长度。
甚至可以优化到O(min), min为word1和word2中较短的长度,

参见Code Ganker大神的解法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值