算法--动态规划

给两个单词word1和word2
求将word1变成word2的最少操作
操作:insert:插入一个字符
delete:删除一个字符
replace:替换一个字符
 
第一次是在leetcode动态规划(leetcode72)看到的,后面做某公司笔试真题的时候又见到了,自己想的太简单了,记录一下解法。
 
动态规划三步:
1.定义数组含义
首先定义word1长度是i,word2长度j,dp[i][j]代表转换的最少操作数
我们要做的是逐一比较word1[1~i]和word2[1~j]
相同 就同时移步 dp[i][j]==dp[i-1][j-1]
不同,有三种操作
替换:直接在word1【i】中替换一个与word2【j】对应位置相同的字符 ,两边需要都移位,操作数+1
dp[i][j]==dp[i-1][j-1] + 1
删除:把字符word[i]删除,用i-1位再继续比较,则 dp[i][j]==dp[i-1][j] + 1
插入:在word1[i]后插入一个与word2[j]相同的字符,即为 dp[i][j]==dp[i][j-1] + 1
 
在我们逐个比较的过程中,需要从这三种操作中选一种,让最后dp[i][j]最小,可以得到一个关系:
dp[i][j] = min{ dp[i][j]==dp[i-1][j-1], dp[i][j]==dp[i-1][j], dp[i][j]==dp[i][j-1] } + 1
 
找初始值
当 i 或 j 为0时,关系式就不在成立,不能进行移位。但是计算也很简单,其中一个为0时,另一个的长度就是最少的操作数。
 
 
public int func(String word1,String word2){
    int len1 = word1.length();
    int len2 = word2.length();
    int[][] dp = new int[len1 + 1][len2 + 1];
    
    //初始值dp[i][j]
    for(int j = 1; j <= len2; j++){
        dp[0][j] = dp[0][j-1] + 1;
    }
    for(int i = 1; i <= len1; i++){
        dp[i][0] = dp[i-1][0] + 1;
    }
    
    for(int i = 1;i<=len1;i++){
        for(int j = 1;j<=len2;j++){
            if(word1.charAt(i-1) == word2.charAt(j-1)){
                dp[i][j] = dp[i-1][j-1];                
            }else{
                dp[i][j] = Math.min(Math.min(dp[i - 1][j - 1], 
                            dp[i][j - 1]), 
                            dp[i - 1][j]) + 1;
            }
        }
    }
    return dp[len1][len2];
}

  

posted @ 2020-12-10 10:57  烨然。  阅读(68)  评论(0)    收藏  举报