72. 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

这题如果直接顺着写一个算法来直接分析这俩字符串,非常不方便,很不好做。这题之所以是leetcode的hard题,就是因为问题本身的复杂性,以及把它转化为常规算法的不明显。事实上,这题可以用递归,divide and conquer, 或者动态规划,dynamic programming来将问题逐步降解,省去了我们各种分析和讨论的步骤,但我们仍需要给出,1. 边界情况(就像之前棋盘问题里的初始化第一行第一列);2. 递推公式,或者state equation,就是一般情况下怎么降解问题或者递推问题。
注意降解问题不一定是一维的,不一定只是对这里的word1,要把两个单词的变化都考虑进去。
分析如下:
1. 如果word1[i] = word2[j],那么此时最后一位可以忽略,这时的最少步骤等于word1[0…i-1]转换为word2[0…j-1]的步骤;
2. 如果不相等。那么我们可以考虑word2[j]这一位可以有几种获得方法。总共只有三种操作可能,删除,插入,替换。如果在最少步骤里是替换,那么最少步骤应该等于word1[0…i-1]转换为word2[0…j-1]加一;如果是删除,最少步骤应该等于word1[0…i-1]转换为word2[0…j]加一;如果是插入,那么就应该等于word[0…i]转化为word2[0…j-1]加一。

这样一来,边界条件和状态转化方程(递推公式)就都有了。

递推公式: dp[i][j] = dp[i-1][j-1] if (A[i] == B[j])
or = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) +1;
初始条件: dp[0][j] = j and dp[i][0] = i

如果用递归做的话,代码如下:

int minDistance(string word1, string word2) {
    int len1 = word1.size();
    int len2 = word2.size();
    return helper(word1, word2, len1, len2);
}
int helper(string word1, string word2, int len1, int len2) {
    if (len1 == 0) return len2;
    if (len2 == 0) return len1;
    if (word1[len1 - 1] == word2[len2 - 1]) return helper(word1, word2, len1-1, len2-1);
    else {
        return min(helper(word1, word2, len1, len2-1), min(helper(word1, word2, len1-1, len2), helper(word1, word2, len1-1, len2-1))) + 1;
    }
}

当然这里分析完问题就知道不应该用递归,因为子问题相互重叠,递归计算量太大,时间复杂度指数型增长,所以上面代码结果正确,但时超时了。

int minDistance(string word1, string word2) {
    int len1 = word1.size();
    int len2 = word2.size();
    int dp[len1 + 1][len2 + 1];
    for (int i = 0; i < len1 + 1; i++) {
        for (int j = 0; j < len2 + 1; j++) {
            if (i == 0) dp[i][j] = j;
            else if (j == 0) dp[i][j] = i;
            else if (word1[i-1] == word2[j-1]) {
                dp[i][j] = dp[i-1][j-1];
            } 
            else {
                dp[i][j] = min(dp[i-1][j-1], min(dp[i-1][j], dp[i][j-1])) + 1;
            }
        }
    }
    return dp[len1][len2];
}

这也是经典的动态规划问题了,牢记。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值