動態規劃常適用於有重疊子問題和最優子結構性質的問題,它的本質是以空間換取時間。
它的模板步驟如下:
按上述步驟進行詳細敘述:
思考狀態
狀態的定義,先試著將題目所求的設定為狀態;然後思考狀態是如何轉移的,如果狀態轉移方程不易得到,嘗試修改定義,目的依然是為了方面得到狀態轉移方程。
思考狀態轉移方程
思考初始化
思考輸出
對於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 ...