[C++][Leetcode][動態規劃]編輯距離

編輯距離算是一個比較經典的問題,可以用於常見的拼寫糾錯。

1.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
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
  • 思路分析

對於兩個字符串,我們從右到左進行比較:

當a[i]==b[i]那麼我們需要做任何操作,操作次數和a[i-1]與b[i-1]的操作次數相同。

如果不相等,那麼我們有三種選擇:第一種,刪除a的當前元素(操作次數1)+以a[i-1]結尾串和以b[i]結尾串的操作次數;第二種,在當前位置插入一個元素,使得其與b[i]相等(操作次數1)+以a[i]結尾串與以b[i-1]結尾串的操作次數;第三種情況,替換a[i]使其等於b[i](操作次數1)+以a[i-1]結尾串和以b[i-1]結尾串的操作次數。在這三種情況裏,選擇一個操作次數最少的。

當其中一個串空是,最短的操作次數就是另外一個串的長度。

  • 代碼設計
    • 遞歸版本
class Solution {
public:
    //遞歸超時
    int MinDistance(string word1,string word2,int w1,int w2)
    {
        if(w1==0)
            return w2;
        else if(w2==0)
            return w1;
        else if(word1[w1-1]==word2[w2-1])
            return MinDistance(word1,word2,w1-1,w2-1);
        
            return 1+min(MinDistance(word1,word2,w1,w2-1),min(MinDistance(word1,word2,w1-1,w2),MinDistance(word1,word2,w1-1,w2-1)));
    }
    int minDistance(string word1, string word2) {
        int w1=word1.size();
        int w2=word2.size();
        return MinDistance(word1,word2,w1,w2);
        
        
        
    }
};
  • 動態規劃版本(時間複雜度N^2,空間複雜度N^2)
class Solution {
public:
    //N*N的空間 N*N的時間複雜度
    
    int minDistance(string word1, string word2) {
        int w1=word1.size();
        int w2=word2.size();
        
        vector<vector<int>>dp(w1+1,vector<int>(w2+1,0));

        //dp[i][j]:表示長度爲i的字符串1與長度爲j的字符串2需要的操作次數

        for(int i=0;i<=w1;++i)
        {
            for(int j=0;j<=w2;++j)
            {
                if(j==0)//如果str2爲空串 把str1全部刪除
                    dp[i][j]=i;
                else if(i==0)//同理s1爲空串
                    dp[i][j]=j;
                else 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],min(dp[i][j-1],dp[i-1][j-1]));
                }
            }
        }

        return dp[w1][w2];
        
        
    }
};
  • 動態規劃改進版本(時間複雜度N^2空間複雜度N)
class Solution {
public:
    //N*N的空間 N*N的時間複雜度
    
    int minDistance(string word1, string word2) {
        int w1=word1.size();
        int w2=word2.size();
        
        vector<vector<int>>dp(2,vector<int>(w1+1,0));
        //其實可以發現我們每次更新的時候 狀態只和其前一行有關係 

        //我們以str1作爲基準 來比如
        for(int i=0;i<=w1;++i)
        {
            dp[0][i]=i;//假設str2爲空
        }

        //i%2的作用就是取交替下標0,1
        for(int i=1;i<=w2;++i)
        {
            for(int j=0;j<=w1;++j)
            {
                if(j==0)//如果str1爲空 i%2=0去當前位置p[0]
                    dp[i%2][j]=i;
                else if(word1[j-1]==word2[i-1])
                    dp[i%2][j]=dp[(i-1)%2][j-1];//和i-1,j-1一樣 
                else
                {
                    dp[i%2][j]=1+min(dp[(i-1)%2][j],min(dp[i%2][j-1],dp[(i-1)%2][j-1]));
                }
            }
        }
        return dp[w2%2][w1];

        
       
        
        
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章