leetcode:72. 最小編輯距離

題目描述:git

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

你能夠對一個單詞進行以下三種操做:ide

插入一個字符
刪除一個字符
替換一個字符
示例 1:code

輸入: word1 = "horse", word2 = "ros"
輸出: 3
解釋:
horse -> rorse (將 'h' 替換爲 'r')
rorse -> rose (刪除 'r')
rose -> ros (刪除 'e')
示例 2:blog

輸入: word1 = "intention", word2 = "execution"
輸出: 5
解釋:
intention -> inention (刪除 't')
inention -> enention (將 'i' 替換爲 'e')
enention -> exention (將 'n' 替換爲 'x')
exention -> exection (將 'n' 替換爲 'c')
exection -> execution (插入 'u')utf-8

# -*- 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]
相關文章
相關標籤/搜索