代码随想录day54 动态规划 编辑距离

代码随想录day54 动态规划

题583 两个字符串的删除操作

1,dp[i][j] 代表以i-1为结尾的字符串word1,和以j-1位结尾的字符串word2,想要达到相等,所需要删除元素的最少次数。
2, 递推公式:
当word1[i - 1] 与 word2[j - 1]相同的时候,不需要再删除元素,dp[i][j] = dp[i - 1][j - 1];
当word1[i - 1] 与 word2[j - 1]不相同的时候,有三种情况:
情况一:删word1[i - 1],最少操作次数为dp[i - 1][j] + 1
情况二:删word2[j - 1],最少操作次数为dp[i][j - 1] + 1
情况三:同时删word1[i - 1]和word2[j - 1],操作的最少次数为dp[i - 1][j - 1] + 2
最后取3种情况中的最小值。

3, 初始化:
dp[i][0]:word2为空字符串,以word[i-1]为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。同理dp[0][j] = j。

4,本题还有另外一个思路,先求出最长公共子序列的长度max,再用word1.length() - max + word2.length() - max .

class Solution {
    public int minDistance(String word1, String word2) {
        int[][] dp = new int[word1.length() + 1][word2.length() + 1];
        for(int i = 0; i <= word1.length(); i++) {
            dp[i][0] = i;
        }
        for(int j = 0; j <= word2.length(); j++) {
            dp[0][j] = j;
        }
        for(int i = 1; i <= word1.length(); i++) {
            char char1 = word1.charAt(i - 1);
            for(int j = 1; j <= word2.length(); j++) {
                char char2 = word2. charAt(j - 1);
                if(char1 == char2) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    //删除word1[i-1],删除word[j-1],两个都删除,取这3种情况中的最小。
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 2);
                }
            }
        }
        return dp[word1.length()][word2.length()];
    }
}

题72 编辑距离

1,编辑距离是用动规来解决的经典题目,这道题目看上去好像很复杂,但用动规可以很巧妙的算出最少编辑距离。
2,同样的,dp[i][j] 表示以下标i-1为结尾的字符串word1,和以下标j-1为结尾的字符串word2,最近编辑距离为dp[i][j]。
3,递推公式:
仍然是分两种情况:
当word1[i - 1] == word2[j - 1], 此时不需要编辑操作,因此dp[i][j] = dp[i - 1][j - 1];
当不想等时就需要编辑,有3种编辑方式:
删除元素:保持word2不变,将word1[i - 1] 删除,就是说不考虑word1[i - 1],则dp[i][j] = dp[i - 1][j] + 1;
插入元素:插入元素相对来说难理解一点,将word2[j-1] 这个字符加到word1[i - 1]的后面,比如"ab" -> “abc”, 当’b’ != 'c’时,将c插入到b的后面,这时只用考虑"ab" -> "ab"所需的最少编辑次数+1(1是代表插入操作),即dp[i][j] = dp[i][j - 1] + 1。
对于增加元素也可以理解为word2删除word2[j-1]这个元素,同时对word1和word2进行编辑,最后得到的字符串相同。
替换元素:将word1[i - 1]替换成word2[j - 1],则dp[i][j] = dp[i - 1][j - 1] + 1。
4,初始化,与两个字符串的删除题目相同,第一行和第一列不再是0, 而是dp[i][0] = i, dp[0][j] = j 。

class Solution {
    public int minDistance(String word1, String word2) {
        int[][] dp = new int[word1.length() + 1][word2.length() + 1];
        for(int i = 0; i <= word1.length(); i++) {
            dp[i][0] = i;
        }
        for(int j = 0; j <= word2.length(); j++) {
            dp[0][j] = j;
        }
        for(int i = 1; i <= word1.length(); i++) {
            char char1 = word1.charAt(i - 1);
            for(int j = 1; j <= word2.length(); j++) {
                char char2 = word2.charAt(j - 1);
                if(char1 == char2) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    // 3种情况(取最小):
                    //删除word1[i-1];
                    //在word1[i-1]后面插入元素word[j-1]; 
                    //将word1[i-1]替换为word[j-1].
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1), dp[i - 1][j - 1] + 1);
                }
            }
        }
        return dp[word1.length()][word2.length()];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值