Edit Distance 编辑距离

编辑距离是一道经典的动态规划(dynamic programing)问题。

下面将详细地介绍解法。

我们先定义一下cache[ i ][ j ] ,表示,要将word1[0...i - 1] 转化成word2[0..j - 1] 的最小步骤。

比如,我们的word1 = "aeee"       world2 = "adef"


  "" a d e f
  ""           
a          
e          
e          
e          

我们先来考虑一下base的情况,当word1 = "", 那么它要多少步骤才能转换成word2[0 ... j  - 1]?

显然至少要 j 步才可以。所以,我们可以得到

1. cache[ i ] [ 0 ] = i;

2. cache[ 0 ][ j ] = j;

  "" a d e f
  "" 0 1 2 3 4
a 1        
e 2        
e 3        
e 4        

接下来我们考虑更general 的情况。

假设我们想要得到word1[0...i - 1] 转化成 word[0..j - 1]

当word[ i - 1] == word[ j - 1 ]  那么我们不用再做其他操作,
cache[ i - 1 ] [ j - 1 ] = cache[ i  - 2] [ j - 2 ] 
(如表中'a' == 'a' 为例,我们可以在表中,填0)

接下来,当word[ i - 1 ] != word[ j  - 1] ,
我们可以有3种选择。
1. 将 word1[i - 1] 替换成 word[ j - 1],   对应着: cache[ i - 1 ] [ j - 1 ] = cache[ i  - 2] [ j - 2 ]  + 1
2. 将 word1[i - 1] 删掉,  对应着:    cache[ i - 1 ] [ j - 1 ]  = cache[ i  - 2] [ j - 1 ] + 1 
3. 将 word[ j - 1] 插入到word[0... i - 1]中, 对应着: cache[ i - 1 ] [ j - 1 ]  =  cache[ i  - 1] [ j - 2 ] + 1 
最终,我们从这3种操作中,选择步数中最小的。

比如在下表,a ! = d 我们可以选择
1. a 替换成d,  需要 1 + 1  = 2步(因为已经知道 "" 转成 "a" 需要1步)
2. a 删掉,  需要 2 + 1 = 3 步 (因为已经知道了 "" 转成 "ad" 需要2步)
3. 插入d,   需要 0 + 1 = 1 步 ( 因为我们已经知道 "a" 转成"a"需要0步)
最终,填1

  "" a d e f
  "" 0 1 2 3 4
a 1 0      
e 2        
e 3        
e 4        

将上述的base case 和 general case 结合起来。
我们得到
1. cache[ i ] [ 0 ] = i;
2. cache[ 0 ] [ j ] = j;
3. 当 i > 0 , j > 0 , 
3.1 如果 word[ i - 1] = word [ j - 1] 
    cache[ i ] [ j ] = cache[ i - 1] [ j - 1] 
 3.2 如果 word[ i - 1] != word[ j - 1]
    cache[ i ] [ j ] = min ( cache[ i - 1] [ j - 1] , cache[ i - 1] [ j ] , cache[ i ] [ j - 1] ) + 1


如我们的表最终会变成这样:

  "" a d e f
  "" 0 1 2 3 4
a 1 0 1 2 3
e 2 1 1 1 2
e 3 2 2 1 2
e 4 3 3 2 2

代码:
    public int minDistance(String word1, String word2) {
        int m = word1.length(), n = word2.length();
        int[][] cache = new int[m + 1][n + 1];
        for (int i = 0; i < m + 1; i++) {
            cache[i][0] = i;
        }
        for (int j = 0; j < n + 1; j++) {
            cache[0][j] = j;
        }
        for (int i = 1; i < m + 1; i++) {
            for (int j = 1; j < n + 1; j++) {
                if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                    cache[i][j] = cache[i - 1][j - 1];
                } else {
                    cache[i][j] = Math.min(Math.min(cache[i][j - 1], cache[i - 1][j]), cache[i - 1][j - 1]) + 1;
                }
            }
        }
        return cache[m][n];
    }



你可能感兴趣的:(leetcode)