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')

# -*- coding: utf-8 -*-
# @Time         : 2019-09-22 16:51
# @Author       : Jayce Wong
# @ProjectName  : job
# @FileName     : 72-editDistance.py
# @Blog         : https://blog.51cto.com/jayce1111
# @Github       : https://github.com/SysuJayce

class Solution:
    """
    從word1->word2,對於word1的每個字符,可以有插入、刪除、替換三種操作。
    碰到這種題我們應該先想到的是這是一道可以用動態規劃解決的問題,因爲我們是要從一個複雜的問題中
    求解一個最優值,而這個複雜問題可以分解成多個子問題。例如,我們已經將word1[:-1]到word2的最小
    編輯距離找到了,那麼再計算word1->word2的編輯距離的時候就會變得容易許多。

    既然已經知道要用到動態規劃,那麼動態規劃的解題步驟就是先找出狀態轉移方程,然後對狀態進行初始化

    假設dp[i][j]代表將word1[:i] -> word2[:j]所需的最小編輯距離,那麼當我們已知dp[i-1][j-1]
    的時候,要求dp[i][j]的話可以有以下兩種情況:
    1. word1[i - 1] == word2[j - 1]:
        這種情況我們不需要對word1[i-1]做任何操作,等價於dp[i-1][j-1]
        即:dp[i][j] = dp[i-1][j-1]
    2. word1[i - 1] != word2[j - 1]:
        這時候我們要想到,我們已經用一個二維的狀態矩陣保存了不同情況下的最優值,應該要想辦法利用已
        知的最優值來找到當前狀態的最優值。

        a) 刪除
        由於我們已知dp[i - 1][j],這代表了將word1[: i - 1]->word2[: j]的最小編輯距離,
        如果我們先將word1[: i - 1]->word2[: j],然後將word1[i - 1]刪除,那麼就可以實現
        word1[:i] -> word2[:j].
        因此,dp[i][j] = dp[i - 1][j] + 1;
        b) 插入
        由於我們已知dp[i][j - 1],這代表了將word1[: i]->word2[: j - 1]的最小編輯距離,
        如果我們先將word1[: i]->word2[: j - 1],然後再在word1[: i]後面增加word2[j - 1]
        那麼就可以實現word1[:i] -> word2[:j]。
        因此,dp[i][j] = dp[i][j - 1] + 1
        c) 替換
        由於我們已知dp[i - 1][j - 1],這代表了將word1[: i - 1]->word2[: j - 1]的
        最小編輯距離,如果我們先將word1[: i - 1]->word2[: j - 1],然後再將word1[i]替換成
        word2[j],那麼就可以實現word1[:i] -> word2[:j]。
        那麼也可以實現word1[:i] -> word2[:j]。
        因此,dp[i][j] = dp[i - 1][j - 1] + 1

        上述的a)b)c)都是可行的,而我們需要的是最小的編輯距離,因此就需要從上述的三種操作中選擇
        最小的一種
    """
    def minDistance(self, word1: str, word2: str) -> int:
        rows = len(word1)
        cols = len(word2)
        # 初始化狀態矩陣
        dp = [[0] * cols for _ in range(rows)]
        for i in range(cols):
            dp[0][i] = i
        for j in range(rows):
            dp[j][0] = j

        # 根據狀態轉換方程進行狀態更新
        for i in range(1, rows):
            for j in range(1, cols):
                if word1[i - 1] == word2[j - 1]:
                    dp[i][j] = dp[i - 1][j - 1]
                else:
                    dp[i][j] = 1 + min(dp[i - 1][j], dp[i][j - 1],
                                       dp[i - 1][j - 1])

        # 動態規劃的最後一個狀態就是我們需要的結果
        return dp[-1][-1]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章