zoukankan      html  css  js  c++  java
  • 力扣算法题—072编辑距离

    给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

    你可以对一个单词进行如下三种操作:

    1. 插入一个字符
    2. 删除一个字符
    3. 替换一个字符

    示例 1:

    输入: word1 = "horse", word2 = "ros"
    输出: 3
    解释: 
    horse -> rorse (将 'h' 替换为 'r')
    rorse -> rose (删除 'r')
    rose -> ros (删除 'e')
    

    示例 2:

    输入: word1 = "intention", word2 = "execution"
    输出: 5
    解释: 
    intention -> inention (删除 't')
    inention -> enention (将 'i' 替换为 'e')
    enention -> exention (将 'n' 替换为 'x')
    exention -> exection (将 'n' 替换为 'c')
    exection -> execution (插入 'u')


     1 #include "_000库函数.h"
     2 
     3 
     4 //不知道从何下手
     5 //参考博客答案
     6 
     7 //要尝试三种操作,因为谁也不知道当前的操作会对后面产生什么样的影响,
     8 //那么对于当前比较的两个字符 word1[i] 和 word2[j],若二者相同,一切好说,
     9 //直接跳到下一个位置。若不相同,有三种处理方法,首先是直接插入一个 word2[j],那么 word2[j] 
    10 //位置的字符就跳过了,接着比较 word1[i] 和 word2[j + 1] 即可。
    11 //第二个种方法是删除,即将 word1[i] 字符直接删掉,接着比较 word1[i + 1] 和 word2[j] 即可。
    12 //第三种则是将 word1[i] 修改为 word2[j],接着比较 word1[i + 1] 和 word[j + 1] 即可。
    13 //分析到这里,我们可以直接写出递归的代码,但是很可惜会 Time Limited Exceed,
    14 //所以我们必须要优化事件复杂度,需要去掉大量的重复计算,
    15 //这里我们使用记忆数组 memo 来保存计算过的状态,从而可以通过OJ,
    16 //注意这里的 insertCnt,deleteCnt,replaceCnt 仅仅是表示当前对应的位置分别采用了插入,删除,和替换操作,
    17 //整体返回的最小距离,后面位置的还是会调用递归返回最小的,参见代码如下:
    18 class Solution {
    19 public:
    20     int minDistance(string word1, string word2) {
    21         int m = word1.size(), n = word2.size();
    22         vector<vector<int>> memo(m, vector<int>(n));
    23         return helper(word1, 0, word2, 0, memo);
    24     }
    25     int helper(string& word1, int i, string& word2, int j, vector<vector<int>>& memo) {
    26         if (i == word1.size()) return (int)word2.size() - j;
    27         if (j == word2.size()) return (int)word1.size() - i;
    28         if (memo[i][j] > 0) return memo[i][j];
    29         int res = 0;
    30         if (word1[i] == word2[j]) {
    31             return helper(word1, i + 1, word2, j + 1, memo);
    32         }
    33         else {
    34             int insertCnt = helper(word1, i, word2, j + 1, memo);
    35             int deleteCnt = helper(word1, i + 1, word2, j, memo);
    36             int replaceCnt = helper(word1, i + 1, word2, j + 1, memo);
    37             res = min(insertCnt, min(deleteCnt, replaceCnt)) + 1;
    38         }
    39         return memo[i][j] = res;
    40     }
    41 };
    42 
    43 //根据以往的经验,对于字符串相关的题目且求极值的问题,
    44 //十有八九都是用动态规划Dynamic Programming来解,这道题也不例外。
    45 //其实解法一的递归加记忆数组的方法也可以看作是DP的递归写法。
    46 //这里我们需要维护一个二维的数组dp,其大小为 mxn,m和n分别为 word1 和word2 的长度。
    47 //dp[i][j] 表示从 word1 的前i个字符转换到 word2 的前j个字符所需要的步骤。那
    48 //我们可以先给这个二维数组dp的第一行第一列赋值,这个很简单,因为第一行和第一列对应的总有一个字符串是空串,
    49 //于是转换步骤完全是另一个字符串的长度。跟以往的DP题目类似,难点还是在于找出状态转移方程,
    50 //我们可以举个例子来看,比如word1是“bbc",word2是”abcd“,那么我们可以得到dp数组如下:
    51 
    52 
    53 //Ø a b c d
    54 //Ø 0 1 2 3 4
    55 //b 1 1 1 2 3
    56 //b 2 2 1 2 3
    57 //c 3 3 2 1 2
    58 //
    59 //
    60 //我们通过观察可以发现,当word1[i] == word2[j]时,dp[i][j] = dp[i - 1][j - 1],
    61 //其他情况时,dp[i][j]是其左,左上,上的三个值中的最小值加1,其实这里的左,上,和左上,
    62 //分别对应的增加,删除,修改操作,具体可以参见解法一种的讲解部分,那么可以得到状态转移方程为:
    63 //
    64 //if word1[i - 1] == word2[j - 1]
    65 //    dp[i][j] = dp[i - 1][j - 1]                                                                   
    66 //else
    67 //    min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1            
    68 //
    69 //
    70 class Solution {
    71 public:
    72     int minDistance(string word1, string word2) {
    73         int m = word1.size(), n = word2.size();
    74         vector<vector<int>> dp(m + 1, vector<int>(n + 1));
    75         for (int i = 0; i <= m; ++i) dp[i][0] = i;
    76         for (int i = 0; i <= n; ++i) dp[0][i] = i;
    77         for (int i = 1; i <= m; ++i) {
    78             for (int j = 1; j <= n; ++j) {
    79                 if (word1[i - 1] == word2[j - 1]) {
    80                     dp[i][j] = dp[i - 1][j - 1];
    81                 }
    82                 else {
    83                     dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1;
    84                 }
    85             }
    86         }
    87         return dp[m][n];
    88     }
    89 };
  • 相关阅读:
    用FileSystemWatcher监视文件系统
    生成随机汉字验证码
    MySQL学习笔记二
    python高级学习笔记
    boost bind 表达式中的是值语义还是指针语义?
    容器与适配器的个人总结
    subversion linux使用方法
    boost asio(初学示例)
    MySQL学习笔记一
    subversion 命令
  • 原文地址:https://www.cnblogs.com/zzw1024/p/10705319.html
Copyright © 2011-2022 走看看