1. 程式人生 > >【LeetCode】72. Edit Distance(C++)

【LeetCode】72. Edit Distance(C++)

地址:https://leetcode.com/problems/edit-distance/

題目:

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

理解:

求兩個字串的編輯距離。
編輯距離的定義是:從字串A到字串B,中間需要的最少操作權重
大概就是通過插入,刪除和替換操作,讓word1變成word2的次數。

實現:

解答裡給出的程式碼倒是能照著敲出來,但是並沒有看懂為什麼。
看到大神給出的解釋Edit Distance,理解後自己也解釋一下:
使用陣列dist[i][j]表示字串word1[0:i-1]word2[0:j-1]的編輯距離,也就是說通過修改,此時word1[0:i-1]word2[0:j-1]已經是相同的字串了。
如何求解dist[i][j]呢?

  • 如果word1[i-1]==word2[j-1]
    ,說明最後的兩個字元也是相同的,不需要改變,則
    d i s t [ i ] [ j ] = d i s t [ i 1 ] [ j 1 ] dist[i][j]=dist[i-1][j-1]
  • 否則,我們有下面幾種方法修改
    d i s t [ i ] [ j ] = m i n ( d i s t [ i 1 ] [ j 1 ] , d i s t [ i 1 ] [ j ] , d i s t [ i ] [ j 1 ] ) + 1 dist[i][j]=min(dist[i-1][j-1],dist[i-1][j],dist[i][j-1])+1
    • word1[i-1]替換為word2[j-1] ,也就是說,需要在dist[i-1][j-1]的基礎上,修改word1[i-1]
    • word1[i-1]刪除,因為dist[i-1][j]給出了word1[0:i-2]修改為word2[0:j-1]的次數,我們只需要把word1[i-1]刪除,又可以重新使得兩個字串相同
    • word1[i-2]後面插入word2[j-1],因為dist[i][j-1]表示word1[0:i-2]==word2[0:i-1],因此插入一個也能保證word1[0:i-1]==word2[0:i-1]
class Solution {
public:
	int minDistance(string word1, string word2) {
		int len1 = word1.length(), len2 = word2.length();
		if (len1*len2 == 0) return len1 + len2;
		vector<vector<int>> dist(len1 + 1, vector<int>(len2 + 1));
		for (int i = 0; i < len1 + 1; ++i)
			dist[i][0] = i;
		for (int j = 0; j < len2 + 1; ++j)
			dist[0][j] = j;
		for (int i = 1; i < len1 + 1; ++i)
			for (int j = 1; j < len2 + 1; ++j) {
				int left = dist[i][j - 1];
				int up = dist[i - 1][j];
				int left_up = dist[i - 1][j - 1] - 1;
				if (word1.at(i - 1) == word2.at(j - 1))
					dist[i][j]=dist[i-1][j-1];
                else
				    dist[i][j]=1 + min(dist[i-1][j-1], min(dist[i][j-1], dist[i-1][j]));
			}
		return dist[len1][len2];
	}
};