题目描述
给你两个单词 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’)
思路&js代码
1、动态规划
🧩 状态定义:
我们用 dp[i][j] 表示将 word1[0..i-1]变为 word2[0..j-1] 的最小操作次数。
🔁 状态转移:
如果 word1[i-1] == word2[j-1],不需要操作:dp[i][j] = dp[i-1][j-1]
否则,取三种操作中最小的一个 + 1:
插入:dp[i][j-1] + 1
删除:dp[i-1][j] + 1
替换:dp[i-1][j-1] + 1
🧱 初始化:
dp[i][0] = i:把前 i 个字符删光
dp[0][j] = j:把目标串插满
/**
* @param {string} word1
* @param {string} word2
* @return {number}
*/
var minDistance = function(word1, word2) {
const m = word1.length;
const n = word2.length;
// 初始化一个 (m+1) x (n+1) 的二维数组,默认值为0
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
// 初始化第一列:将 word1 前 i 个字符删除
for (let i = 0; i <= m; i++) {
dp[i][0] = i;
}
// 初始化第一行:将 word2 的前 j 个字符插入
for (let j = 0; j <= n; j++) {
dp[0][j] = j;
}
// 填表格,从 dp[1][1] 开始
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
// 默认取三种操作中的最小值 + 1
dp[i][j] = Math.min(
dp[i - 1][j - 1], // 替换
dp[i - 1][j], // 删除
dp[i][j - 1] // 插入
) + 1;
// 如果当前字符相等,就可以直接继承,不操作
if (word1[i - 1] === word2[j - 1]) {
dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - 1]);
}
}
}
// 返回将 word1 转为 word2 的最小操作数
return dp[m][n];
};