72. 编辑距离
题目描述
给了两个单词word1和word2,问如果将word1转化为word2需要最少操作数?
可以怎么操作?插入字符,删除字符,替换字符
f1-动态规划-自底向上 |
基本分析
- 先明确可能的操作有几种?6种
- 以上6种有没有等价的,可以减少思考维度?有等价的,最后剩3种,word1增加,word1删除,word1修改
- 怎么定义状态?比较常见,定义为f[i][j]表示word1的前i个字符修改为word2的前j个字符的最少,因为考虑有0,0的情况,比字符长度多定义一位
- 考虑怎么转移?(1)分析第i位个第j位的关系,相同则可用f[i-1][j-1]转移;(2)不相同则在3个操作(删、增加、改)中取最小
- 对某个词是0的情况怎么进行边界处理?区分word1和word2是0的情况。(1)word1是0,锁定f[i]是0, 需要在列的维度上逐个字符去加;(2)word2是0,锁定f[j]是0,需要在行的维度上逐个去加
代码
class Solution: def minDistance(self, word1: str, word2: str) -> int: m, n = len(word1), len(word2) f = [[0]*(n+1) for _ in range(m+1)] # 预处理都是0的情况 f[0][0] = 0 # word2是0的情况,对应word1删除 for i in range(1, m+1): f[i][0] = f[i-1][0] + 1 # word1是0的情况,对应word1增加 for j in range(1, n+1): f[0][j] = f[0][j-1] + 1 # 其他情况,取3种可能最小 for i in range(1, m+1): for j in range(1, n+1): if word1[i-1] == word2[j-1]: f[i][j] = f[i-1][j-1] else: f[i][j] = min(f[i-1][j-1], f[i][j-1], f[i-1][j]) + 1 return f[-1][-1]
复杂度
时间:
空间:
总结
涉及这种2个字符串匹配的,考虑最少是两个维度,看有没有可能前i去满足前j
这里操作比较多,需要考虑有没有可能等价,这里把6转化成了3
这里的操作针对的是前i个前j,删除、增加、修改并没有限定位置
在转移的时候,根据末尾做了分类,相同简单,不同是3个的最小+1
定义状态的时候考虑要不要多定义一位?前0位在dp里面是有意义的,所以多定义了一位,在写末尾判断的时候,需要注意索引是第几位-1
对首行和首列的边界条件,可以先预处理了,这样一般情况的dp转移不用考虑太多边界
f2-状态压缩+自顶向下 |
基本分析
其他同上,这里考虑怎么用记忆化搜索实现
- 和dp的区别?(1)两个的方向不一样,dp是00时候知道结果,搜索是终点知道结果(某一个达到长度);(2)传递时候已知的方向不一样,一个前一个后
- 怎么写搜索?(1)参数:处理到的索引,从0开始;(2)结束情况:某一个单词达到了长度,剩余就能口算了,特别的,这里可以考虑边界上的情况;(2)转移:某位等和不等两种情况;(3)返回:最少次数
代码
class Solution: def minDistance(self, word1: str, word2: str) -> int: m, n = len(word1), len(word2) @cache def helper(i, j): # 达到了word1的长度: if i == m: return n-j # 达到了word2的长度 if j == n: return m-i if word1[i] == word2[j]: return helper(i+1, j+1) else: ins = helper(i+1, j) + 1 dele = helper(i, j+1) + 1 rep = helper(i+1, j+1) + 1 return min(ins, dele, rep) return helper(0, 0)
复杂度
时间:
空间:
总结
需要注意两者方向上的差别,导致在已知状态+递归方向上的区别
另外判定索引和单词长度的写法,避免了额外边界的讨论
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现