- 题目链接:https://leetcode-cn.com/problems/edit-distance/
- 使用Python3进行编码。
1、带备忘录的递归
# 递归+备忘录
class Solution:
def minDistance(self, s1, s2) -> int:
memo = dict()
# 定义:dp(i, j) 返回 s1[0..i] 和 s2[0..j] 的最小编辑距离
def dp(i, j):
# base case
# 表示s1已从后向前遍历结束,s2此时索引为j,可将0~j索引之间的(j+1)个元素全部删除
if i == -1: return j + 1
# 原理同上
if j == -1: return i + 1
if (i, j) in memo:
return memo[(i, j)]
if s1[i] == s2[j]:
memo[(i, j)] = dp(i - 1, j - 1) # 啥都不做
else:
memo[(i, j)] = min(
dp(i, j - 1) + 1, # 插入
dp(i - 1, j) + 1, # 删除
dp(i - 1, j - 1) + 1 # 替换
)
return memo[(i, j)]
# i,j 初始化指向最后一个索引
return dp(len(s1) - 1, len(s2) - 1)
2、动态规划(dp数组与方法一的函数定义不同)
# 动态规划
class Solution:
def minDistance(self, s1, s2) -> int:
m = len(s1)
n = len(s2)
# 定义:dp[i][j]存储s1[0...i-1],s2[0...j-1]的最小编辑距离
dp = [[0] * (n + 1) for _ in range(m + 1)]
# base case
for i in range(1, m + 1):
dp[i][0] = i
for j in range(1, n + 1):
dp[0][j] = j
# 自底向上求解
for i in range(1, m + 1):
for j in range(1, n + 1):
# 注意:此处和自顶向下的递归方法的条件不同,跟dp数组定义有关,i-1,j-1代表末尾索引
if s1[i - 1] == s2[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)
# 存储着整个s1和s2的最小编辑距离
return dp[m][n]