• LeetCode----72. 编辑距离


     题目

    给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数

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

    插入一个字符
    删除一个字符
    替换一个字符
    
    • 1
    • 2
    • 3

    示例 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’)

    提示:

    0 <= word1.length, word2.length <= 500
    word1 和 word2 由小写英文字母组成
    
    • 1
    • 2

     解答

    这是一个经典的编辑距离(Levenshtein距离)问题,可以使用动态规划来解决。编辑距离是从一个字符串转换为另一个字符串所需的最少操作数,操作包括插入、删除和替换字符。

    以下是Java代码示例,实现了计算编辑距离的函数:

    class Solution {
        public int minDistance(String word1, String word2) {
            int m = word1.length();
            int n = word2.length();
            
            // 创建一个二维数组dp,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作数
            int[][] dp = new int[m + 1][n + 1];
            
            // 初始化dp数组
            for (int i = 0; i <= m; i++) {
                dp[i][0] = i;  // 将word1转换为空字符串,需要i次删除操作
            }
            for (int j = 0; j <= n; j++) {
                dp[0][j] = j;  // 将空字符串转换为word2,需要j次插入操作
            }
            
            // 填充dp数组
            for (int i = 1; i <= m; i++) {
                for (int j = 1; j <= n; j++) {
                    if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                        dp[i][j] = dp[i - 1][j - 1];  // 字符相同,无需操作
                    } else {
                        // 取三种操作中的最小值,加1表示执行当前操作
                        int insert = dp[i][j - 1] + 1;  // 插入操作
                        int delete = dp[i - 1][j] + 1;  // 删除操作
                        int replace = dp[i - 1][j - 1] + 1;  // 替换操作
                        dp[i][j] = Math.min(Math.min(insert, delete), replace);
                    }
                }
            }
            
            return dp[m][n];
        }
    }
    
    • 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

    这段代码使用动态规划来填充一个二维数组dp,在dp[i][j]中存储了将word1的前i个字符转换为word2的前j个字符所需的最少操作数。最终返回dp[m][n],其中mn分别是word1word2的长度。

    这个算法的时间复杂度为O(m*n),其中m和n是输入字符串的长度。

    编辑距离(Edit Distance),也称为Levenshtein距离,是用于衡量两个字符串之间的相似度的数学概念。它表示将一个字符串转换为另一个字符串所需的最小编辑操作次数。这些编辑操作可以是插入字符、删除字符或替换字符。
    编辑距离通常使用动态规划算法来计算,其中一个常见的动态规划算法是上面提到的Levenshtein距离算法。该算法计算了两个字符串之间的编辑距离,以确定它们之间的相似性。编辑距离越小,两个字符串越相似。

    除了动态规划,编辑距离还可以使用递归和记忆化搜索来解决。以下是递归和记忆化搜索的Java代码示例:

     递归解法:

    class Solution {
        public int minDistance(String word1, String word2) {
            return editDistance(word1, word2, word1.length(), word2.length());
        }
        
        private int editDistance(String word1, String word2, int m, int n) {
            if (m == 0) {
                return n;  // 插入n个字符
            }
            if (n == 0) {
                return m;  // 删除m个字符
            }
            
            if (word1.charAt(m - 1) == word2.charAt(n - 1)) {
                return editDistance(word1, word2, m - 1, n - 1);  // 字符相同,无需操作
            } else {
                int insert = editDistance(word1, word2, m, n - 1) + 1;  // 插入操作
                int delete = editDistance(word1, word2, m - 1, n) + 1;  // 删除操作
                int replace = editDistance(word1, word2, m - 1, n - 1) + 1;  // 替换操作
                return Math.min(Math.min(insert, delete), replace);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    记忆化搜索解法:

    class Solution {
        public int minDistance(String word1, String word2) {
            int m = word1.length();
            int n = word2.length();
            Integer[][] memo = new Integer[m + 1][n + 1];
            return editDistance(word1, word2, m, n, memo);
        }
        
        private int editDistance(String word1, String word2, int m, int n, Integer[][] memo) {
            if (m == 0) {
                return n;  // 插入n个字符
            }
            if (n == 0) {
                return m;  // 删除m个字符
            }
            
            if (memo[m][n] != null) {
                return memo[m][n];
            }
            
            if (word1.charAt(m - 1) == word2.charAt(n - 1)) {
                memo[m][n] = editDistance(word1, word2, m - 1, n - 1, memo);  // 字符相同,无需操作
            } else {
                int insert = editDistance(word1, word2, m, n - 1, memo) + 1;  // 插入操作
                int delete = editDistance(word1, word2, m - 1, n, memo) + 1;  // 删除操作
                int replace = editDistance(word1, word2, m - 1, n - 1, memo) + 1;  // 替换操作
                memo[m][n] = Math.min(Math.min(insert, delete), replace);
            }
            
            return memo[m][n];
        }
    }
    
    • 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
  • 相关阅读:
    重测序基因组:Pi核酸多样性计算
    【软件设计师21天-考点整理】7)计算机系统构成及硬件基础知识
    正大美欧4的主账户关注什么数据?
    开源python双屏图片浏览器软件
    leetcode18 四数之和 双指针
    js---async和awit的一些理解
    教程更新20220719
    Project 1 2022 - see also project 1 clarifications and the sample solution
    码农跃迁三角色:程序员、技术主管与架构师
    二十二、W5100S/W5500+RP2040树莓派Pico<SMTP发送邮件>
  • 原文地址:https://blog.csdn.net/u011095039/article/details/134251618