LeetCode分類02 動態規劃

2021-10-23 15:22:50 字數 4097 閱讀 9747

動態規劃常適用於有重疊子問題和最優子結構性質的問題,它的本質是以空間換取時間。

它的模板步驟如下:

按上述步驟進行詳細敘述:

思考狀態

狀態的定義,先試著將題目所求的設定為狀態;然後思考狀態是如何轉移的,如果狀態轉移方程不易得到,嘗試修改定義,目的依然是為了方面得到狀態轉移方程。

思考狀態轉移方程

思考初始化

思考輸出

對於q1:給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。

從回文串的定義思考:如果乙個字串的頭尾兩個字元都不相等,那麼這個字串一定不是回文串;

如果乙個字串的頭尾兩個字元相等,進一步討論:如果裡面的字串是回文,則整體是回文串;如果裡面的子串不是回文串,整體就不是回文串。

頭尾字元相等的情況下,裡面子串是否為回文串決定了整個子串是否為回文串,因此可以將狀態定義為遠字串的乙個子串是否為回文子串。

定義狀態

dp[i][j]表示子串s[i...j]是否為回文子串,這裡子串s[i...j]為閉區間。

思考狀態轉移方程

動態規劃實際上相當於填一張二維**,由於考慮子串,因此,i小於等於j,也就是只需要填**的右上部分。

邊界條件:如果表示式[i+1 , j-1]不構成區間,即長度嚴格小於2,即j-1-(i+1)+1<2,整理得j-i<3

這個結論很顯然:當子串s[i...j]的長度等於2或者3的時候,只需要判斷一下頭尾兩個字元是否相等可直接下結論。

如果子串s[i+1...j-1]只有1個字元,即去掉兩頭,剩下中間部分只有1個字元,顯然是回文;

如果子串s[i+1...j-1]為空串,那麼子串s[i , j]一定是回文子串。

因此,在s[i] == s[j],成立j-i<3的前提下,直接可以下結論,dp[i][j] = true,否則才執行狀態轉移。

** 考慮初始化**

初始化的時候,單個字元一定是回文串,因此把對角線先初始化為true,即dp[i][j] = true

考慮輸出

當得到dp[i][j] = true,就立即記錄子串的長度和起始位置。

class

solution

(object):

deflongestpalindrome

(self, s)

:"""

:type s: str

:rtype: str

"""n =

len(s)

if n <2:

return s

start =

0 max_len =

1 dp =[[

false

for _ in

range

(n)]

for _ in

range

(n)]

for i in

range

(n):

dp[i]

[i]=

true

for j in

range(1

,n):

for i in

range

(j):

if s[i]

== s[j]

:if j-i+

1<=3:

dp[i]

[j]=

true

else

: dp[i]

[j]= dp[i+1]

[j-1

]else

: dp[i]

[j]=

false

if dp[i]

[j]:

cur_len = j-i+

1if cur_len>max_len:

max_len = cur_len

start = i

return s[start:start+max_len]

對於q2:給你兩個單詞 word1 和 word2,請你計算出將 word1 轉換成 word2 所使用的最少運算元 。你可以對乙個單詞進行如下三種操作:

插入乙個字元

刪除乙個字元

替換乙個字元

定義狀態

dp[i][j]定義為word1中前i個字元轉化成word2中前j個字元需要的最少步數。

思考狀態轉移方程

word1[i] == word2[j]時,dp[i][j] = dp[i-1][j-1]

word1[i] != word2[j]時,dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1

其中,dp[i-1][j-1]代表替換操作,dp[i-1][j]表示刪除操作,dp[i][j-1]表示增加操作。

初始化

dp[i][j] = 0

class

solution

(object):

defmindistance

(self, word1, word2)

:"""

:type word1: str

:type word2: str

:rtype: int

"""m =

len(word1)

n =len(word2)

# 加了邊界條件,多加一行一列

dp =[[

0for _ in

range

(n+1)]

for _ in

range

(m+1)]

for i in

range

(n+1):

dp[0]

[i]= i # 對於第一行,每次都是在之前基礎上新增乙個操作

for j in

range

(m+1):

dp[j][0

]= j #第一列也是

for i in

range(1

,m+1):

for j in

range(1

,n+1):

if word1[i-1]

== word2[j-1]

: dp[i]

[j]= dp[i-1]

[j-1

]else

: dp[i]

[j]=

min(dp[i]

[j-1

],dp[i-1]

[j],dp[i-1]

[j-1])

+1return dp[-1

][-1

]

LeetCode分類訓練 Task 2動態規劃

群內編號 2 木鐸鐸 博文內容學習自datawhale開源文件 leetcode分類訓練 task 2 動態規劃 動態規劃常常適用於有重疊子問題和最優子結構性質的問題,動態規劃方法所耗時間往往遠少於樸素解法。要解乙個給定問題,需解其不同子問題,再根據子問題的解得出原問題的解。動態規劃 dp 往往用於...

Leetcode 02動態規劃

ac 72.編輯距離 198.打家劫舍 213.打家劫舍 ii 516.最長回文子串行 674.最長連續遞增序列 題目鏈結 class solution return result bool ispalindrome string s return true 判斷完是回文串 參考解答 class s...

LeetCode 目標和(深度優先搜尋 動態規劃)

給定乙個非負整數陣列,a1,a2,an,和乙個目標數,s。現在你有兩個符號 和 對於陣列中的任意乙個整數,你都可以從 或 中選擇乙個符號新增在前面。返回可以使最終陣列和為目標數 s 的所有新增符號的方法數。示例 1 輸入 nums 1,1,1,1,1 s 3 輸出 5 解釋 1 1 1 1 1 3 ...