leetCode 72.Edit Distance (編輯距離) 解題思路和方法
阿新 • • 發佈:2018-12-24
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
因為本題的替換操作權重同樣為1,故字元不相等+1即可。自然語言處理(NLP)中,有一個基本問題就是求兩個字串的minimal Edit Distance, 也稱Levenshtein distance。受到一篇Edit Distance介紹文章的啟發,本文用動態規劃求取了兩個字串之間的minimal Edit Distance. 動態規劃方程將在下文進行講解。 1. what is minimal edit distance? 簡單地說,就是僅通過插入(insert)、刪除(delete)和替換(substitute)個操作將一個字串s1變換到另一個字串s2的最少步驟數。熟悉演算法的同學很容易知道這是個動態規劃問題。 其實一個替換操作可以相當於一個delete+一個insert,所以我們將權值定義如下: I (insert):1 D (delete):1 S (substitute):2 2. example: intention->execution Minimal edit distance: delete i ; n->e ; t->x ; insert c ; n->u 求和得cost=8 3.calculate minimal edit distance dynamically 思路見註釋,這裡D[i,j]就是取s1前i個character和s2前j個character所得minimal edit distance 三個操作動態進行更新: D(i,j)=min { D(i-1, j) +1, D(i, j-1) +1 , D(i-1, j-1) + s1[i]==s2[j] ? 0 : 2};中的三項分別對應D,I,S。(詳見我同學的部落格)
程式碼如下:
public class Solution { public int minDistance(String word1, String word2) { //邊界條件 if(word1.length() == 0) return word2.length(); if(word2.length() == 0) return word1.length(); /* * 本題用動態規劃的解法 * f[i][j]表示word1的前i個單詞到word2前j個單詞的最短距離 * 狀態轉移方程:f[i][j] = */ int[][] f = new int[word1.length()][word2.length()]; boolean isEquals = false;//是否已經有相等 for(int i = 0 ; i < word2.length(); i++){ //如果相等,則距離不增加 if(word1.charAt(0) == word2.charAt(i) && !isEquals){ f[0][i] = i > 0 ? f[0][i-1]:0;//不能從0開始 isEquals = true; }else{ f[0][i] = i > 0 ? f[0][i-1]+1:1; } } isEquals = false;//是否已經有相等 for(int i = 1 ; i < word1.length(); i++){ //如果相等,則距離不增加 if(word1.charAt(i) == word2.charAt(0) && !isEquals){ f[i][0] = f[i-1][0];//不能從0開始 isEquals = true; }else{ f[i][0] = f[i-1][0]+1; } } for(int i = 1; i < word1.length();i++){ for(int j = 1; j < word2.length(); j++){ if(word1.charAt(i) == word2.charAt(j)){ f[i][j] = f[i-1][j-1];//相等的話直接相等 }else{ f[i][j] = f[i-1][j-1]+1; } //然後與從f[i-1][j]+1,f[i][j-1]+1比較,取最小值 f[i][j] = Math.min(f[i][j],Math.min(f[i-1][j]+1,f[i][j-1]+1)); } } return f[word1.length()-1][word2.length()-1]; } }