1. 问题背景与理解
LeetCode 72题"Edit Distance"是动态规划领域的经典问题,也是各大科技公司面试中的高频考题。这道题要求我们计算将一个单词转换成另一个单词所需的最少操作次数,允许的操作包括插入、删除和替换字符。
我第一次遇到这个问题是在准备某大厂面试时,当时被它的简洁描述和巧妙解法所吸引。经过反复练习和教学实践,我发现这道题能很好地考察以下几个核心能力:
- 对字符串操作的敏感度
- 动态规划思想的灵活运用
- 边界条件的处理能力
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动态规划解法详解
2.1 状态定义与转移方程
我们定义dp[i][j]表示将word1的前i个字符转换为word2的前j个字符所需的最小操作次数。状态转移方程需要考虑三种情况:
-
如果word1[i-1] == word2[j-1](注意字符串索引从0开始):
dp[i][j] = dp[i-1][j-1] // 无需操作 -
如果字符不相等:
dp[i][j] = min(
dp[i-1][j] + 1, // 删除word1[i-1]
dp[i][j-1] + 1, // 在word1插入word2[j-1]
dp[i-1][j-1] + 1 // 替换word1[i-1]为word2[j-1]
)
关键提示:这个转移方程是理解整个问题的核心,建议在纸上画出2x2的简单例子手动推导。
2.2 初始化边界条件
边界情况处理是动态规划容易出错的地方:
- dp[0][j] = j:空字符串变为word2前j个字符需要j次插入
- dp[i][0] = i:word1前i个字符变为空字符串需要i次删除
python复制# 初始化代码示例
m, n = len(word1), len(word2)
dp = [[0]*(n+1) for _ in range(m+1)]
for i in range(m+1):
dp[i][0] = i
for j in range(n+1):
dp[0][j] = j
3. 完整实现与优化
3.1 Python实现版本
python复制def minDistance(word1: str, word2: str) -> int:
m, n = len(word1), len(word2)
dp = [[0]*(n+1) for _ in range(m+1)]
# 初始化边界
for i in range(m+1):
dp[i][0] = i
for j in range(n+1):
dp[0][j] = j
# 填充dp表
for i in range(1, m+1):
for j in range(1, n+1):
if word1[i-1] == word2[j-1]:
dp[i][j] = dp[i-1][j-1]
else:
dp[i][j] = min(
dp[i-1][j] + 1,
dp[i][j-1] + 1,
dp[i-1][j-1] + 1
)
return dp[m][n]
3.2 空间优化技巧
原始解法空间复杂度是O(mn),可以优化到O(min(m,n)):
python复制def minDistance_optimized(word1: str, word2: str) -> int:
if len(word1) < len(word2):
word1, word2 = word2, word1
m, n = len(word1), len(word2)
prev = list(range(n+1))
for i in range(1, m+1):
curr = [i] + [0]*n
for j in range(1, n+1):
if word1[i-1] == word2[j-1]:
curr[j] = prev[j-1]
else:
curr[j] = min(
prev[j] + 1,
curr[j-1] + 1,
prev[j-1] + 1
)
prev = curr
return prev[n]
4. 常见错误与调试技巧
4.1 典型错误案例
- 索引越界:忘记字符串索引从0开始,导致dp[i][j]对应的是word1[i-1]和word2[j-1]
- 初始化错误:没有正确处理空字符串的情况
- 状态转移遗漏:漏掉三种操作中的某一种
4.2 调试方法
- 打印dp表:对于小例子手动验证
python复制word1 = "horse"
word2 = "ros"
print(minDistance(word1, word2))
# 可以打印出完整的dp表检查
- 边界测试:
- 两个空字符串
- 一个空字符串和一个非空字符串
- 两个完全相同的字符串
- 两个完全不同但长度相同的字符串
5. 复杂度分析与变种问题
5.1 时间复杂度分析
- 时间复杂度:O(mn),需要填充m×n的dp表
- 空间复杂度:
- 基础版本:O(mn)
- 优化版本:O(min(m,n))
5.2 相关变种问题
- 只有插入和删除操作(不允许替换)
- 每种操作有不同的代价
- 输出具体的操作序列而不仅仅是次数
- 判断两个字符串是否在k次操作内可以转换
6. 实际应用场景
编辑距离算法在现实中有广泛应用:
- 拼写检查与自动更正
- DNA序列比对
- 文档相似度计算
- 语音识别中的候选词排序
我在实际工作中曾用它来实现一个智能搜索建议功能,当用户输入可能有拼写错误时,系统会自动推荐最接近的正确词汇。
7. 学习建议与进阶路线
对于想深入掌握这类问题的同学,我建议的学习路径:
- 先理解基础解法,能手动推导小例子
- 尝试不同的实现语言(Python/Java/C++)
- 解决LeetCode上的相似问题:
-
- Longest Common Subsequence
-
- Delete Operation for Two Strings
-
- Minimum ASCII Delete Sum for Two Strings
-
- 阅读经典算法书籍中动态规划相关章节
最后分享一个调试小技巧:当遇到dp问题时,先用2x2或3x3的最小例子手动计算预期结果,再与程序输出对比,这样能快速定位逻辑错误。
