leetcode 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
碰到这道题目时,首先想到的解法是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操作。
得到这组状态转移方程后,问题就简单啦。
下面给出代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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 } } |
这道题告诉我们,动态规划中的中间态不一定是一维的而可能是二维的
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步