LeetCode 72 編輯距離

LeetCode 72 編輯距離

題目

給定兩個單詞 word1 和 word2,計算出將 word1 轉換成 word2 所使用的最少操作數 。

你可以對一個單詞進行如下三種操作:

插入一個字符
刪除一個字符
替換一個字符
示例 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’)

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/edit-distance
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

分析及代碼

步驟一、定義數組元素的含義
由於我們的目的求將 word1 轉換成 word2 所使用的最少操作數 。那我們就定義 dp[i] [j]的含義爲:當字符串 word1 的長度爲 i,字符串 word2 的長度爲 j 時,將 word1 轉化爲 word2 所使用的最少操作次數爲 dp[i] [j]。
有時候,數組的含義並不容易找,所以還是那句話,我給你們一個套路,剩下的還得看你們去領悟。
步驟二:找出關係數組元素間的關係式
接下來我們就要找 dp[i] [j] 元素之間的關係了,比起其他題,這道題相對比較難找一點,但是,不管多難找,大部分情況下,dp[i] [j] 和 dp[i-1] [j]、dp[i] [j-1]、dp[i-1] [j-1] 肯定存在某種關係。因爲我們的目標就是,**從規模小的,通過一些操作,推導出規模大的。對於這道題,我們可以對 word1 進行三種操作
插入一個字符 刪除一個字符 替換一個字符
由於我們是要讓操作的次數最小,所以我們要尋找最佳操作。那麼有如下關係式:
一、如果我們 word1[i] 與 word2 [j] 相等,這個時候不需要進行任何操作,顯然有 dp[i] [j] = dp[i-1] [j-1]。(別忘了 dp[i] [j] 的含義哈)。
二、如果我們 word1[i] 與 word2 [j] 不相等,這個時候我們就必須進行調整,而調整的操作有 3 種,我們要選擇一種。三種操作對應的關係試如下(注意字符串與字符的區別):
(1)、如果把字符 word1[i] 替換成與 word2[j] 相等,則有 dp[i] [j] = dp[i-1] [j-1] + 1;
(2)、如果在字符串 word1末尾插入一個與 word2[j] 相等的字符,則有 dp[i] [j] = dp[i] [j-1] + 1;
(3)、如果把字符 word1[i] 刪除,則有 dp[i] [j] = dp[i-1] [j] + 1;
那麼我們應該選擇一種操作,使得 dp[i] [j] 的值最小,顯然有
dp[i] [j] = min(dp[i-1] [j-1],dp[i] [j-1],dp[[i-1] [j]]) + 1;
於是,我們的關係式就推出來了,
步驟三、找出初始值
顯然,當 dp[i] [j] 中,如果 i 或者 j 有一個爲 0,那麼還能使用關係式嗎?答是不能的,因爲這個時候把 i - 1 或者 j - 1,就變成負數了,數組就會出問題了,所以我們的初始值是計算出所有的 dp[0] [0….n] 和所有的 dp[0….m] [0]。這個還是非常容易計算的,因爲當有一個字符串的長度爲 0 時,轉化爲另外一個字符串,那就只能一直進行插入或者刪除操作了。

以上的引用自知乎https://zhuanlan.zhihu.com/p/91582909?utm_source=qq&utm_medium=social&utm_oi=967379295711166464

以下是自己的感受,這道題相比網格和最小路徑和題目,相比難一點。因爲創建數組並找出元素的含義相比要難一些。上面的分析之後,還是略微有點不太理解,後面還有更多的題目,比這道題更難理解一點。

代碼

import numpy as np
class Solution:
    def minDistance(self,word1: str, word2: str) -> int:
        n1 = len(word1)
        n2 = len(word2)
        ans = list(np.zeros((n1+1, n2+1)).astype(int))   # 注意數組的大小是(n1+1,n2+1)
        ans[0][0] = 0
        for i in range(1, n1+1):
            ans[i][0] = ans[i-1][0]+1
        for i in range(1, n2+1):
            ans[0][i] = ans[0][i-1]+1
        for i in range(1, n1+1):
            for j in range(1, n2+1):
                # 這裏要判斷下 第i個和第j個字符是否相同
                if word1[i-1] == word2[j-1]:   # 一定要注意這裏都要減1,不然會報錯
                    ans[i][j] = ans[i-1][j-1]
                else:
                    ans[i][j] = min(ans[i-1][j-1], ans[i-1][j], ans[i][j-1])+1
        return ans[n1][n2]

這種二維數組的解法最後提交後,運行時間和空間都不是特別好。後續補充如何優化。

發佈了53 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章