动态规划-解决编辑距离的问题

本文介绍了LeetCode第72题的解题思路和动态规划解决方案。通过编辑距离问题,展示了如何使用动态规划计算两个单词之间的最小编辑距离。文章详细解释了动态规划数组的定义、递推公式以及初始化数据,并给出了相应的Java代码实现。
摘要由CSDN通过智能技术生成

这是LeetCode的72题,好久没有做动态规划了,所以碰到这道题,第一反应完全没有想到动态规划,所以记录下来,以提示自己,同时也分享给大家,我写的不好,也可以参照官方题解

原题

72. 编辑距离
给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数  。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
 

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

解题思路

dp数组解释

题目就说了,这个一道动态规划问题,所以直接先上dp数组,我取名称:records,定义和特点如下

  • records[i][j]:将word1前i个字符 和 word2 前j个字符编辑成相等,需要多少步
  • records[i][j]中i每增加一1,就相当于word1的字符的下标右移动一位,这个是不需要步骤的,也就是解题的关键
递推公式

record[i][j]:数值的来源可以有3个
1. 在record[i][j-1]基础上 :直接插入一个字符,步骤需要+1
2. 从record[i-1][j-1]中来 : 这个要分2中情况,由于i增加了,所以word1[i] == word2[j],那么不增加任何步骤,还等于record[i-1][j-1],否则需要替换字符,步骤+1
3. 从record[i-1][j]中来 :这个i增加了1,所以需要删除新增加的字符,才能和原来相等,所以步骤+1

初始化数据

这里有2个特殊情况,可以提前初始化好

  1. records[0][j] :当空字符串word1变成word2需要的步骤,自然,word2有多少个字符,就需要多少步骤(全部是插入)
  2. records[i][0] :将word1变成空字符的需要的步骤,同上,全部是删除的步骤,长度和i相关

根据上面,大家可以手动的填一下dp数组,效果如下(网上找的图片,红框不用管):
在这里插入图片描述

代码

class Solution {
 /*records[i][j]:将word1前i个字符 和 word2 前j个字符都相等,需要多少步
    特点:records[i][j]中i每增加一1,相当于records[i-1][j]的基础上自动增加了一个word1的字符
     record[i][j]:的来可以有3个方向
        1. 从record[i][j-1]中直接插入一个字符,步骤需要+1
        2. 从record[i-1][j-1]:这个要分2中情况,由于i增加了,所以word1[i] == word2[j],那么不增加任何步骤,还等于record[i-1][j-1],否则需要替换字符,步骤+1
        3. 从record[i-1][j]中来:这个i增加了1,所以需要删除新增加的字符
        预备工作:
        要先初始化:
        1.当空字符,变成word2需要的步骤,自然,word2有多少个字符,就需要多少步骤(全部是插入)
        2. 将word1变成空字符的需要的步骤,同上,全部是删除的步骤
    */
    public int minDistance(String word1, String word2) {
        int m = word1.length() + 1;
        int n = word2.length() + 1;
        int[][] records = new int[m][n];
        //records[i][j] 的值可以有下面3种情况转换而来
        for(int i = 0; i < m;i++){
            records[i][0] = i;
        }
        for(int j = 0;j < n;j++){
            records[0][j] = j;
        }
        int min = 0;
        for(int i = 1;i < m;i++){
            for(int j = 1;j < n;j++){
                if(word1.charAt(i-1) == word2.charAt(j-1)){
                    records[i][j] = records[i-1][j-1];
                } else {
                    min = Math.min(records[i][j-1],records[i-1][j-1]);
                    records[i][j] = Math.min(min,records[i-1][j]) + 1;
                }
            }
        }
        return records[m-1][n-1];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值