1. 程式人生 > >LeetCode之計算字串相似度或編輯距離EditDistance

LeetCode之計算字串相似度或編輯距離EditDistance

問題描述:

/**
 * 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
*/

兩個字串的相似度就是計算一個字串轉化為另一個字串需要的步數steps,插入一個字元算一步,刪除一個字元算一步,替換一個字元算一步。所以也叫作編輯距離。
很明顯這是一個動態規劃問題。宣告一個數組arr[i][j]表示字串word1[0…i-1]到word2[0…j-1]的距離。
在arr[i+1][j+1]和arr[i][j]之間有一個關係,比如word1結束字元為x,word2結束字元為y:
如果x=y,則arr[i+1][j+1]=arr[i][j];
如果x!=y,則我們可以從word1裡刪除一個元素,arr[i+1][j+1]=arr[i+1][j]+1;
我們也可以從word1插入一個元素,arr[i+1][j+1]=arr[i][j+1]+1;
我們也可以從word1替換一個元素,arr[i+1][j+1]=arr[i][j]+1;
我們可以用下圖來解釋一下上面的公式:

    a p p l e
  0 1 2 3 4 5
a 1 0 1 2 3 4
p 2 1 0 1 2 3
p 3 2 1 0 1 2

首先要初始化arr陣列,arr[i][0]=i,arr[0][j]=j;這樣初始化的含義對照上圖就是說,arr[i][0]=i;即如果word2為空,那麼要把word2轉化為app,分別需要0,1,2,3步,也就是word2增加’a’,增加’p’,增加’p’。
arr[0][j]表示,word1從無到轉化為word2 “apple”需要0,1,2,3,4,5步,即增加’a’,增加’p’,增加’p’,增加’l’,增加’e’。

word1的一個字元想要轉化成word2,有3種方法:替換,刪除,增加
這裡寫圖片描述

每次轉化時都要加1,因為這算1步。這樣上面三個公式得以解決。

具體程式碼如下:

public int minDistance(String word1, String word2) {
        if (word1.length() == 0 || word2.length() == 0)
            return word1.length() == 0 ? word2.length() : word1.length();
        int[][] arr = new int[word1.length() + 1][word2.length() + 1];
        for (int i = 0; i <= word1.length(); i++) {
            arr[i][0] = i;
        }
        for (int j = 0; j <= word2.length(); j++) {
            arr[0][j] = j;
        }
        for (int i = 0; i < word1.length(); i++) {
            for (int j = 0; j < word2.length(); j++) {
                if (word1.charAt(i) == word2.charAt(j)) {
                    arr[j + 1][i + 1] = arr[j][i];
                } else {
                    int replace = arr[i][j]+1 ;
                    int insert = arr[i][j + 1]+1 ;
                    int delete = arr[i + 1][j]+1 ;

                    int min = replace > insert ? insert : replace;
                    min = delete > min ? min : delete;
                    arr[i + 1][j + 1] = min;
                }
            }
        }
        return arr[word1.length()][word2.length()];
    }