72. 编辑距离
-
解题思路
- 直接暴力递归,
process(i, j)
:word1[i...]
转换成word2[j...]
需要的最少操作次数,也就是说,i字符之前的不用处理了,已经变成了j字符之前的了。 - 如果
word1[i] == word2[j]
- 可以什么操作都不干,i和j就完成了,所以返回
process(i + 1, j + 1)
- 也可以插入一个字符
word2[j]
,所以返回process(i, j + 1) + 1
,注意这里操作了一次要加1. - 也可以删除一个字符,所以返回
process(i + 1, j) + 1
- 可以什么操作都不干,i和j就完成了,所以返回
- 如果
word1[i] != word2[j]
- 可以替换成
word2[j]
,所以返回process(i + 1, j + 1) + 1
- 可以插入一个字符
word2[j]
,所以返回process(i, j + 1) + 1
- 可以删除一个字符,所以返回
process(i + 1, j) + 1
- 可以替换成
- 为了写代码好看,可以在相等的时候,也加一个「替换字符」的操作(虽然替换字符的操作肯定是不会是最优解)。
- 递归函数,两个可变参数,所以直接加缓存就行,这就是「自顶向下」的动态规划。
- 直接暴力递归,
-
代码
class Solution { public: int process(const string& s1, const string &s2, int i, int j, vector<vector<int>> &dp) { if (i == s1.size() && j == s2.size()) { // 都到结尾了 不需要操作了 返回0 return 0; } if (i == s1.size()) { // 只能在后面加字符了 return s2.size() - j; } if (j == s2.size()) { // 只能把后面的字符删除了 return s1.size() - i; } if (dp[i][j] != -1) { return dp[i][j]; } // 删除操作 int del_res = process(s1, s2, i + 1, j, dp) + 1; // 插入操作 int insert_res = process(s1, s2, i, j + 1, dp) + 1; // 替换操作 int replace_res = process(s1, s2, i + 1, j + 1, dp) + 1; int do_nothing = INT32_MAX; // 这种情况不一定有 相等的时候才有 if (s1[i] == s2[j]) { do_nothing = process(s1, s2, i + 1, j + 1, dp); } dp[i][j] = min(del_res, min(insert_res, min(replace_res, do_nothing))); return dp[i][j]; } int minDistance(string word1, string word2) { int n = word1.size(); int m = word2.size(); vector<vector<int>> dp(n, vector<int>(m, -1)); return process(word1, word2, 0, 0, dp); } };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理