LeetCode 72. 编辑距离(java代码和思路分析)

题目传送门

解题思路:

这道题很经典的dp问题。
首先我们只有三种操作:

  1. 删除一个字符
  2. 添加一个字符
  3. 修改一个字符

我们需要用最少的步数将word1转成word2。
我们可以发现以下规律:

  • 从word1变成word2不可能是先删掉一个字符,再把这个字符加回来,这样平白无故的多出了两次操作,肯定不是最少步数
  • 我们操作的顺序并不影响结果,比如abcd编程ace,需要删除bd添加e,这三步我们先做哪一步结果都是一样的

dp的要素:

考虑集合的表示:
f[i][j], 用这个二维数组表示。表示word1的前i个字符编程word2的前j个字符的所有操作方法。值代表了需要的最少步数。

考虑状态计算(状态转移方程):
由第二个规律我们从前往后做(从前往后扫描字符串改变)。
如果我们想要word1的前i个字符和word2的前j个字符相同,因为是从前往后做的,所以有以下几种情况。

  1. word1添加一个字符和word2一样。这需要word1的前i个和word2的前j-1个相同。即f[i][j] = f[i][j-1] + 1。这个地方是因为如果word1的前i个和word2的前j-1个相同,那只需要word1添加一个字符和word2[j]相同即可。
  2. word1删除一个字符和word2一样。这需要word1的前i-1个和word2的前j个相同。即f[i][j] = f[i-1][j] + 1
  3. word1修改一个字符和word2一样。需要保证word1的前i-1个和word2的前j-1个相同。然后判断是否word1[i]=word2[j]。即f[i][j] = f[i-1][j-1] + t。如果word1[i]=word2[j],t = 0,否则t = 1。

有的写还有三种,那三种是word2向word1变,状态方程和上面三个分别对应。这里不写。

代码实现:

class Solution {
    public int minDistance(String word1, String word2) {
        int len1 = word1.length(), len2 = word2.length();
        // dp问题从1走比较好,不用考虑边界,所有加一个空格
        word1 = " " + word1;
        word2 = " " + word2;
        int[][] f = new int[len1 + 5][len2 + 5];
        // 合法的初始化,一个单词变成另一个时
        // 如果从当前变成对方的前0个字符,那只能一直删除
        // 所以有多少个字符最少距离就是几
        for (int i = 0; i <= len1; i ++ ) f[i][0] = i;
        for (int i = 0; i <= len2; i ++ ) f[0][i] = i;
        for (int i = 1; i <= len1; i ++ ) 
            for (int j = 1; j <= len2; j ++ ) {
            	// 前两种情况
                f[i][j] = Math.min(f[i - 1][j], f[i][j - 1]) + 1;
                int t = 0;
                if(word1.charAt(i) != word2.charAt(j)) t = 1;
                // 第三种情况
                f[i][j] = Math.min(f[i][j], f[i - 1][j - 1] + t);
            }
        return f[len1][len2];
    }
}
©️2020 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值