华为OD面试手撕代码:编辑距离
题目
编辑距离
给你两个单词 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')
提示:
- 0 <= word1.length, word2.length <= 500
- word1 和 word2 由小写英文字母组成
代码
/* 编辑距离问题是一个经典的动态规划(Dynamic Programming)问题。我们可以使用动态规划来解决这个问题,其中状态转移方程可以描述为: 1. 如果 word1[i] 等于 word2[j],则 dp[i][j] = dp[i-1][j-1],即不进行任何操作,保持相同。 2. 如果 word1[i] 不等于 word2[j],则可以进行三种操作中的一种: 插入:dp[i][j] = dp[i][j-1] + 1,即在 word1[i] 后插入一个与 word2[j] 相同的字符,使 word1 和 word2 相同。 删除:dp[i][j] = dp[i-1][j] + 1,即删除 word1[i],使 word1 和 word2 相同。 替换:dp[i][j] = dp[i-1][j-1] + 1,即将 word1[i] 替换为 word2[j],使 word1 和 word2 相同。 */ public class Main { public static void main(String[] args) { Solution solution = new Solution(); // 示例 1 String word1 = "horse"; String word2 = "ros"; int result1 = solution.minDistance(word1, word2); System.out.println("示例 1 输出:" + result1); // 输出:3 // 示例 2 String word3 = "intention"; String word4 = "execution"; int result2 = solution.minDistance(word3, word4); System.out.println("示例 2 输出:" + result2); // 输出:5 } } class Solution { /** * 计算两个字符串的最小编辑距离 * 编辑距离指的是将一个字符串转换成另一个字符串所需要的最少操作次数,操作包括插入一个字符、删除一个字符、替换一个字符 * * @param word1 第一个字符串 * @param word2 第二个字符串 * @return 两个字符串的最小编辑距离 */ public int minDistance(String word1, String word2) { int m = word1.length(); // word1的长度 int n = word2.length(); // word2的长度 // 创建二维数组dp,dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最少操作数 int[][] dp = new int[m + 1][n + 1]; // 初始化第一行和第一列 for (int i = 0; i <= m; i++) { dp[i][0] = i; } for (int j = 0; j <= n; j++) { dp[0][j] = j; } // 动态规划求解 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 dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j])) + 1; } } } return dp[m][n]; // 返回最小编辑距离 } }