標籤:
首先給出題目:
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
碰到這道題目時,首先想到的解法是backtracing,即暴力的搜尋整個解空間,求出最優解。結果逾時
百度了一下,知道這題使用的是動態規劃的解法。
既然是動態規劃,那麼解法的關鍵是狀態轉移方程。之前我也曾考慮過動態規劃,然未果。
當時考慮的狀態轉移方程是
根據word1的長度來設計,即,dp[i]表示word1的字串subString(0,i)操作到word2所需的最少步數。但是這個
狀態轉移方程的問題在於,實際上只有一種方案,就是從空串不停的插入,直到變成word2.
然而正確的設計方法是二維的。
dp[i][j]表示將word1.subString(0,i)轉變為word2.subString(0,j)所需的最小步數。
那麼我們就有狀態轉移dp[i+1][j+1]=min{
1.dp[i-1][j]+1
2.dp[i][j-1]+1
3.dp[i-1][j-1]+f(i,j)
}
依次解釋1,2,3
1.我們知道,dp[i-1][j]表示word1.subString(0,i-1)轉變為word2.subString(0,j)所需的最小步數。
例如,word1="abcde",word2="xyzhg",i=3,j=4;
則從abc轉變為xyzhg需要最少k步,那麼從abcd轉變為xyzhg需要多少步?
那麼將abcd的d刪除掉,得到abc,又abc轉變為xyzhg最少要k步,所以通過刪除操作,可以實現從abcd變為xyzhg至少要k+1步
2.與1同理,從abcd變為xyzh最少需要k步,那麼只需將abcd變為xyzh之後,再insert一個g,即可變為xyzhg.
3.f(i,j)表示,if(word1[i]==word2[j]) return 0; else return 1;
即,如果當前index,兩個待處理字元都相等的話,那麼dp[i][j]=dp[i-1][j-1],反之,則需要一個replace操作。
得到這組狀態轉移方程後,問題就簡單啦。
下面給出代碼
public class Solution {/** * @param args */ public int minDistance(String word1, String word2) { if(word1.equals("")&&word2.equals("")) return 0; int row=word1.length()+1; int col=word2.length()+1; int [][]dp=new int[row][col]; for(int i=0;i<row;i++) { dp[i][0]=i; } for(int i=0;i<col;i++) { dp[0][i]=i; } for(int i=1;i<row;i++) for(int j=1;j<col;j++) { if(word1.charAt(i-1)==word2.charAt(j-1)) dp[i][j]=dp[i-1][j-1]; else dp[i][j]=dp[i-1][j-1]+1; dp[i][j]=min(dp[i][j],dp[i-1][j]+1,dp[i][j-1]+1); } return dp[row-1][col-1]; } public int min(int a1,int a2,int a3) { if(a1<a2) { if(a1<a3) return a1; else return a3; } else { if(a2<a3) return a2; else return a3; } }public static void main(String[] args) {// TODO Auto-generated method stub}}
這道題告訴我們,動態規劃中的中間態不一定是一維的而可能是二維的
leetcode edit distance