力扣解題思路 583 兩個字串的刪除操作

2021-10-08 23:43:28 字數 3973 閱讀 8356

思路:刪除兩個字串的字元使它們相等:

input:

"sea"

,"eat"

output:

2explanation: you need one step to make "sea" to "ea" and another step to make "eat" to "ea"

.

———————————更新———————————

這一題,我又一次沒有想到最長公共子串行的方法,採用了最土的遞迴法?而且還超時!

int min = integer.max_value;

public

intmindistance

(string word1, string word2)

public

void

helper

(string word1,string word2,

int start1,

int start2,

int num)

if(start1 == word1.

length()

|| start2 == word2.

length()

)if(word1.

charat

(start1)

== word2.

charat

(start2)

)else

}

當我準備使用記憶化遞迴時發現我的遞迴函式並沒有返回值。。。所以無法為visited陣列賦值,因此我還是轉戰動態規劃了。。。

public

intmindistance

(string word1, string word2)

else}}

return dp[word1.

length()

][word2.

length()

];}

然後就順利一次通過,再次記錄一下我的錯誤思路!

———————分割線(這裡是年前寫的)———————

這一題顯然可以使用動態規劃,這裡提供兩種動態規劃的思路。我們用dp[i][j]表示的word1的前i個字元與word2的前j個字元達到相同所需的最小步數,更新規則如下:

(1)如果word1.charat(i-1) == word2.charat(j-1),那麼不需要刪除任何字元,dp[i][j]的值和dp[i - 1][j - 1]的值相同:dp[i][j] = dp[i - 1][j - 1];

(2)如果word1[i - 1] == word2[j - 1]不成立則需要考慮是刪除word1.charat(i-1)還是 word2.charat(j-1),取其中最小的即可,但是無論word1.charat(i-1) == word2.charat(j-1)是否成立,都有:

dp[i][j] = math.min(dp[i][j],math.min(dp[i-1][j]+1,dp[i][j-1]+1));

然後按照更新規則更新即可:

for

(int i=

1;i<=word1.

length()

;i++

) dp[i]

[j]= math.

min(dp[i]

[j],math.

min(dp[i-1]

[j]+

1,dp[i]

[j-1]+

1));

}}

但是這裡需要注意的是,我們一定要對dp陣列初始化,將最開始的所有值設定為最大值,如果不初始化則在遍歷陣列是min之後最小值永遠是0,例如dp[i][0]和dp[0][j]也需要賦初始值(相當於乙個空串和乙個字串比較,當然返回值就是那個字串的長度了,也就是全部刪去即可)

for

(int i=

0;i<=word1.

length()

;i++

) arrays.

fill

(dp[i]

,integer.max_value)

;for

(int i=

0;i<=word1.

length()

;i++

) dp[i][0

]= i;

for(

int j=

0;j<=word2.

length()

;j++

) dp[0]

[j]= j;

完整**如下:

public

intmindistance

(string word1, string word2)

dp[i]

[j]= math.

min(dp[i]

[j],math.

min(dp[i-1]

[j]+

1,dp[i]

[j-1]+

1));

}}return dp[word1.

length()

][word2.

length()

];}

當然還有另乙個比較巧妙地思路,將該題轉換為求兩個字串的最長公共子串行問題,那最後結果就是刪去除最長公共子串行的長度即可(之前寫過最長公共子串行的題解,不懂的可以戳這裡ο(=•ω<=)ρ⌒☆):

public

intmindistance

(string word1, string word2)

else}}

return m + n -

2* dp[m]

[n];

}

另外,dfs也可以用來解這一題,也是先求最長公共子串行然後返回s1.length() + s2.length() - 2 * lcs(s1, s2, s1.length(), s2.length())即可:

public

intmindistance

(string s1, string s2)

public

intlcs

(string s1, string s2,

int m,

int n)

當然也可以從字串首部開始遍歷:

public

intmindistance

(string s1, string s2)

public

intlcs

(string s1, string s2,

int m,

int n)

但是不幸的是,這兩個dfs方法都超時了,接下來對dfs方法進行優化,我們採用記憶化回溯。我們知道在dfs過程中會不斷的回溯,同的 i 和 j 值在不同的函式呼叫路徑中會重複求解,儘管可能在前某次回溯中已經求解過該值了。只要相同的 i 和 j 對應的函式被呼叫一次,我們可以使用 memo 陣列儲存相應函式的返回值來避免後續訪問的冗餘。memo[i][j] 被用來儲存函式呼叫 lcs(s1, s2, i, j)的返回值。實際上這就是變相的動態規劃,而memo[i][j]相當於dp陣列:

public

intmindistance

(string s1, string s2)

public

intlcs

(string s1, string s2,

int m,

int n,

int[

] memo)

這樣就不會超出時間限制了,這證明通過返回已經在 memo 陣列中儲存的值,我們可以給搜尋過程極大程度的剪枝。

583 兩個字串的刪除操作

給定兩個單詞 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步數,每步可以刪除任意乙個字串中的乙個字元。示例 1 說明 1.給定單詞的長度不超過500。2.給定單詞中的字元只含有小寫字母。為了求得最少刪除次數,我們可以求出串 s1和串 s2最長公共子串行,我們記為 ...

583 兩個字串的刪除操作

題目描述 給定兩個單詞 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步數,每步可以刪除任意乙個字串中的乙個字元。解題思路 動態規劃,和最長公共子串行相似,根據當前結尾的兩個字元是否相等選擇不同的轉移方式,如下 class solution def mindista...

583 兩個字串的刪除操作

題目描述 給定兩個單詞 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步數,每步可以刪除任意乙個字串中的乙個字元。示例 輸入 sea eat 輸出 2 解釋 第一步將 sea 變為 ea 第二步將 eat 變為 ea 給定單詞的長度不超過500。給定單詞中的字元只含...