zoukankan      html  css  js  c++  java
  • [LintCode] Edit Distance

    Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.)

    You have the following 3 operations permitted on a word:

    • Insert a character
    • Delete a character
    • Replace a character
    Example

    Given word1 = "mart" and word2 = "karma", return 3.

    Solution 1. Recursion 

    i is the last character's index in word1, j is the last character's index in word2.

    Recursive functions:

    f(i, j) = Math.min(1 + Math.min(f (i - 1, j), f(i, j - 1) ),   f(i - 1, j - 1)),  if word1.charAt(i) == word2.charAt(j);

    f(i, j) = Math.min(1 + Math.min(f (i - 1, j), f(i, j - 1) ),   1 + f(i - 1, j - 1)), if word1.charAt(i) != word2.charAt(j);

    Base case:

    i < 0 && j < 0: both words are empty, no operations is needed;

    i < 0 && j >= 0: word1 empty but word2 not empty, j + 1 deletions is needed;

    i >= 0 && j < 0: word1 not empty word2 empty, i + 1 deletions is needed;

     1 public class Solution {
     2     public int minDistance(String word1, String word2) {
     3         if(word1 == null || word2 == null){
     4             return Integer.MAX_VALUE;
     5         }
     6         return helper(word1, word1.length() - 1, word2, word2.length() - 1);
     7     }
     8     private int helper(String word1, int idx1, String word2, int idx2){
     9         if(idx1 < 0 && idx2 < 0){
    10             return 0;
    11         }
    12         else if(idx1 < 0){
    13             return idx2 + 1;
    14         }
    15         else if(idx2 < 0){
    16             return idx1 + 1;
    17         }
    18         if(word1.charAt(idx1) == word2.charAt(idx2)){
    19             return Math.min(1 + Math.min(helper(word1, idx1- 1, word2, idx2), helper(word1, idx1, word2, idx2 - 1)), helper(word1, idx1 - 1, word2, idx2 - 1));
    20         }
    21         return Math.min(1 + Math.min(helper(word1, idx1- 1, word2, idx2), helper(word1, idx1, word2, idx2 - 1)), 1 + helper(word1, idx1 - 1, word2, idx2 - 1));
    22     }
    23 }

    Solution 2. Top down DFS search with Memoization, (Dynamic Programming in essence)

    Solution 1 does a lot of duplicate work by computing answers of the same subproblems over and over.

    Caching subproblems' results with memoization optimizes on solution 1. 

     1 public class Solution {
     2     private int[][] T;
     3     public int minDistance(String word1, String word2) {
     4         if(word1 == null || word2 == null){
     5             return Integer.MAX_VALUE;
     6         }
     7         T = new int[word1.length()][word2.length()]; 
     8         for(int i = 0; i < word1.length(); i++){
     9             for(int j = 0; j < word2.length(); j++){
    10                 T[i][j] = Integer.MAX_VALUE;
    11             }
    12         }
    13         return helper(word1, word1.length() - 1, word2, word2.length() - 1);
    14     }
    15     private int helper(String word1, int idx1, String word2, int idx2){
    16         if(idx1 < 0 && idx2 < 0){
    17             return 0;
    18         }
    19         else if(idx1 < 0){
    20             return idx2 + 1;
    21         }
    22         else if(idx2 < 0){
    23             return idx1 + 1;
    24         }
    25         if(T[idx1][idx2] != Integer.MAX_VALUE){
    26             return T[idx1][idx2];
    27         }
    28         int r = Integer.MAX_VALUE;
    29         if(word1.charAt(idx1) == word2.charAt(idx2)){
    30             r = Math.min(1 + Math.min(helper(word1, idx1- 1, word2, idx2), helper(word1, idx1, word2, idx2 - 1)), helper(word1, idx1 - 1, word2, idx2 - 1));
    31         }
    32         else{
    33             r = Math.min(1 + Math.min(helper(word1, idx1- 1, word2, idx2), helper(word1, idx1, word2, idx2 - 1)), 1 + helper(word1, idx1 - 1, word2, idx2 - 1));            
    34         }
    35         T[idx1][idx2] = r;
    36         return r;
    37     }
    38 }

    Solution 3. Bottom up dynamic programming

    State functions are derived directly from the above recursive solution. 

    dp[i][j]: the minimum number of operations needed to covert word1's first ith characters to word2's first jth characters.

    Function: 

    if(word1.charAt(i - 1) == word2.charAt(j - 1)){
        dp[i][j] = Math.min(1 + Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
    }
    else{
        dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
    }

      

    Initializations:

    dp[i][0]: delete a character from word1 i times;

    dp[0][j]: insert a character to word1 j times;

     1 public class Solution {
     2     public int minDistance(String word1, String word2) {
     3         if(word1 == null || word2 == null){
     4             return Integer.MAX_VALUE;
     5         }
     6         int[][] dp = new int[word1.length() + 1][word2.length() + 1];
     7         dp[0][0] = 0;
     8         for(int i = 1; i <= word1.length(); i++){
     9             dp[i][0] = i;
    10         }
    11         for(int j = 1; j <= word2.length(); j++){
    12             dp[0][j] = j;
    13         }
    14         for(int i = 1; i <= word1.length(); i++){
    15             for(int j = 1; j <= word2.length(); j++){
    16                 if(word1.charAt(i - 1) == word2.charAt(j - 1)){
    17                     dp[i][j] = Math.min(1 + Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
    18                 }
    19                 else{
    20                     dp[i][j] = 1 + Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]);
    21                 }
    22             }
    23         }
    24         return dp[word1.length()][word2.length()];
    25     }
    26 }

    Related Problems

    Edit Distance II

  • 相关阅读:
    jQuery碎语(1) 基础、选择要操作的元素、处理DOM元素
    C#位运算符的基本用法
    如何使用==操作符,Equals方法,ReferenceEquals方法,IEquatable接口比较2个对象
    C#实现ATM自动取款机
    如何使用C#关键字const,readonly,static
    用最简单的例子理解适配器模式(Adapter Pattern)
    前缀方式增1和后缀方式增1的区别
    抽象类可以有构造函数吗
    为什么使用抽象类,什么时候使用抽象类
    checked和unchecked的区别
  • 原文地址:https://www.cnblogs.com/lz87/p/7052357.html
Copyright © 2011-2022 走看看