72、最小编辑距离
动态规划:
dp[i][j]代表 word1 到 i 位置转换成word2 到 j 位置需要最少步数
所以,
当 word1[i] == word2[j],dp[i][j] = dp[i-1][j-1];
当 word1[i] != word2[j],dp[i][j] = min(dp[i-1][j-1], dp[i-1][j], dp[i][j-1]) + 1
其中,dp[i-1][j-1] 表示替换操作,dp[i-1][j] 表示删除操作,dp[i][j-1]表示插入操作。
注意,针对第一行,第一列要单独考虑,我们引入 '' 下图所示:
第一行,是 word1 为空变成 word2 最少步数,就是插入操作
第一列,是 word2 为空,需要的最少步数,就是删除操作
自底向上
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
l1 = len(word1)
l2 = len(word2)
path_matrix = [[0 for _ in range(l1+1)] for _ in range(l2+1)]
# path_matrix[0][:] = [i for i in range(l1+1)]
# path_matrix[:][0] = [i for i in range(l2+1)]
for w2 in range(l2+1):
for w1 in range(l1+1):
if w2 == 0 or w1 == 0:
path_matrix[w2][w1] = max(w2, w1)
continue
if word1[w1-1] == word2[w2-1]:
path_matrix[w2][w1] = path_matrix[w2-1][w1-1]
else:
path_matrix[w2][w1] = min(path_matrix[w2-1][w1-1],
path_matrix[w2-1][w1],
path_matrix[w2][w1-1]) + 1
return path_matrix[l2][l1]
自顶向下
class Solution:
def minDistance(self, word1: str, word2: str) -> int:
import functools
@functools.lru_cache(None)
def helper(i, j):
if i == len(word1) or j == len(word2):
return len(word1) - i + len(word2) - j
if word1[i] == word2[j]:
return helper(i + 1, j + 1)
else:
inserted = helper(i, j + 1)
deleted = helper(i + 1, j)
replaced = helper(i + 1, j + 1)
return min(inserted, deleted, replaced) + 1
return helper(0, 0)
自顶向下的思考:
从矩阵的0,0位置到i,j位置要向下走i步,向右走j步。
helper(i,j)代表的含义是,从0,0到i,j一步未动,helper(0,0)是指全部消耗完i,j次移动。
helper函数中的第一个if实际在填充上图矩阵的第一行或第一列。