[LeetCode] Edit Distance

This is a classic problem of Dynamic Programming. We define the state dp[i][j] to be the minimum number of operations to convert word1[0..i - 1] to word2[0..j - 1]. The state equations have two cases: the boundary case and the general case. Note that in the above notations, both i and j take values starting from 1.

For the boundary case, that is, to convert a string to an empty string, it is easy to see that the mininum number of operations to convert word1[0..i - 1] to "" requires at least i operations (deletions). In fact, the boundary case is simply:

  1. dp[i][0] = i;
  2. dp[0][j] = j.

Now let's move on to the general case, that is, convert a non-empty word1[0..i - 1] to another non-empty word2[0..j - 1]. Well, let's try to break this problem down into smaller problems (sub-problems). Suppose we have already known how to convert word1[0..i - 2] to word2[0..j - 2], which is dp[i - 1][j - 1]. Now let's consider word[i - 1] and word2[j - 1]. If they are euqal, then no more operation is needed and dp[i][j] = dp[i - 1][j - 1]. Well, what if they are not equal?

If they are not equal, we need to consider three cases:

  1. Replace word1[i - 1] by word2[j - 1] (dp[i][j] = dp[i - 1][j - 1] + 1 (for replacement));
  2. Delete word1[i - 1] and word1[0..i - 2] = word2[0..j - 1] (dp[i][j] = dp[i - 1][j] + 1 (for deletion));
  3. Insert word2[j - 1] to word1[0..i - 1] and word1[0..i - 1] + word2[j - 1] = word2[0..j - 1] (dp[i][j] = dp[i][j - 1] + 1 (for insertion)).

Make sure you understand the subtle differences between the equations for deletion and insertion. For deletion, we are actually converting word1[0..i - 2] to word2[0..j - 1], which costs dp[i - 1][j], and then deleting the word1[i - 1], which costs 1. The case is similar for insertion.

Putting these together, we now have:

  1. dp[i][0] = i;
  2. dp[0][j] = j;
  3. dp[i][j] = dp[i - 1][j - 1], if word1[i - 1] = word2[j - 1];
  4. dp[i][j] = min(dp[i - 1][j - 1] + 1, dp[i - 1][j] + 1, dp[i][j - 1] + 1), otherwise.

The above state equations can be turned into the following code directly.

复制代码
 1 class Solution { 
 2 public:
 3     int minDistance(string word1, string word2) { 
 4         int m = word1.length(), n = word2.length();
 5         vector<vector<int> > dp(m + 1, vector<int> (n + 1, 0));
 6         for (int i = 1; i <= m; i++)
 7             dp[i][0] = i;
 8         for (int j = 1; j <= n; j++)
 9             dp[0][j] = j;  
10         for (int i = 1; i <= m; i++) {
11             for (int j = 1; j <= n; j++) {
12                 if (word1[i - 1] == word2[j - 1]) 
13                     dp[i][j] = dp[i - 1][j - 1];
14                 else dp[i][j] = min(dp[i - 1][j - 1] + 1, min(dp[i][j - 1] + 1, dp[i - 1][j] + 1));
15             }
16         }
17         return dp[m][n];
18     }
19 };
复制代码

Well, you may have noticed that each time when we update dp[i][j], we only need dp[i - 1][j - 1], dp[i][j - 1], dp[i - 1][j]. In fact, we need not maintain the full m*n matrix. Instead, maintaing one column is enough. The code can be optimized to O(m) or O(n) space, depending on whether you maintain a row or a column of the original matrix.

The optimized code is as follows.

复制代码
 1 class Solution { 
 2 public:
 3     int minDistance(string word1, string word2) {
 4         int m = word1.length(), n = word2.length();
 5         vector<int> cur(m + 1, 0);
 6         for (int i = 1; i <= m; i++)
 7             cur[i] = i;
 8         for (int j = 1; j <= n; j++) {
 9             int pre = cur[0];
10             cur[0] = j;
11             for (int i = 1; i <= m; i++) {
12                 int temp = cur[i];
13                 if (word1[i - 1] == word2[j - 1])
14                     cur[i] = pre;
15                 else cur[i] = min(pre + 1, min(cur[i] + 1, cur[i - 1] + 1));
16                 pre = temp;
17             }
18         }
19         return cur[m]; 
20     }
21 }; 
复制代码

Well, if you find the above code hard to understand, you may first try to write a two-column version that explicitly maintains two columns (the previous column and the current column) and then simplify the two-column version into the one-column version like the above code :-)

posted @   jianchao-li  阅读(201)  评论(0编辑  收藏  举报
编辑推荐:
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
阅读排行:
· 官方的 MCP C# SDK:csharp-sdk
· 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· 一文搞懂MCP协议与Function Call的区别
· 如何不购买域名在云服务器上搭建HTTPS服务
点击右上角即可分享
微信分享提示