面試程式碼題(華為)編輯距離

NewCoder1024發表於2020-03-12

描述

Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.

You have the following 3 operations permitted on a word:

  1. Insert a character
  2. Delete a character
  3. Replace a character

Example 1:

Input: word1 = "horse", word2 = "ros"
Output: 3
Explanation: 
horse -> rorse (replace 'h' with 'r')
rorse -> rose (remove 'r')
rose -> ros (remove 'e')複製程式碼

Example 2:

Input: word1 = "intention", word2 = "execution"
Output: 5
Explanation: 
intention -> inention (remove 't')
inention -> enention (replace 'i' with 'e')
enention -> exention (replace 'n' with 'x')
exention -> exection (replace 'n' with 'c')
exection -> execution (insert 'u')複製程式碼

思路

動態規劃 01揹包問題中,其中的知乎專欄詳細的講解了這個問題。(但是我看到這個專欄的時候已經考完試了,故考試時未能答出:),似乎帶點難度的題我都沒能答出來)

大部分情況下,dp[i] [j] dp[i-1] [j]dp[i] [j-1]dp[i-1] [j-1] 肯定存在某種關係。

字串 word1 的長度為 i,字串 word2 的長度為 j 時,將 word1 轉化為 word2 所使用的最少操作次數為 dp[i] [j],即使用ij來代表兩個字串的狀態。


有時候,陣列的含義並不容易找,還得看自己去領悟。


  1. 如果我們 word1[i]word2 [j] 相等,這個時候不需要進行任何操作,顯然有 dp[i] [j] = dp[i-1] [j-1],即最短編輯距離不變。
  2. 如果我們 word1[i]word2 [j] 不相等,這個時候我們就必須進行調整,而調整的操作有 3 種,我們要選擇一種。三種操作對應的關係試如下(最短編輯距離都要+1):
  • 如果把字元 word1[i] 替換成與 word2[j] 相等,則有 dp[i] [j] = dp[i-1] [j-1] + 1,即在兩個字串分別為i、j的基礎上;
  • 如果在字串 word1末尾插入一個與 word2[j] 相等的字元,則有 dp[i] [j] = dp[i] [j-1] + 1;
  • 如果把字元 word1[i] 刪除,則有 dp[i] [j] = dp[i-1] [j] + 1;


關係式為dp[i] [j] = min(dp[i-1] [j-1],dp[i] [j-1],dp[[i-1] [j]]) + 1;

class Solution {
    public int minDistance(String word1, String word2) {
        int s1Len = word1.length(), s2Len = word2.length();
        int dp[][] = new int[s1Len+1][s2Len+1];
        //對邊界值進行計算
        //即邊界值只能通過上一個邊界值+1得來,
        //因為一個字串長度為0時,和另一個字串的最短編輯距離差只有增加一種情況。
        dp[0][0] = 0;
        for(int i = 1; i<s1Len+1; i++){
            dp[i][0] = dp[i-1][0] + 1;
        }
        for(int i = 1; i<s2Len+1; i++){
            dp[0][i] = dp[0][i-1] + 1;
        }

        //填表過程
        for(int i = 1; i<s1Len+1; i++){
            for(int j = 1; j<s2Len+1; j++){
                if(word1.charAt(i-1) == word2.charAt(j-1)){
                    dp[i][j] = dp[i-1][j-1];
                }else{
                    dp[i][j] = Math.min(Math.min(dp[i-1][j-1], dp[i-1][j]), dp[i][j-1])+1;
                }
            }
        }
        return dp[s1Len][s2Len];
    }
}複製程式碼
Runtime: 5 ms, faster than 84.06% of Java online submissions for Edit Distance.
Memory Usage: 42 MB, less than 5.88% of Java online submissions for Edit Distance.

找到陣列的含義對解題至關重要,因為它決定著動態規劃的核心——關係式


相關文章