動態規劃合集

2021-08-26 14:55:23 字數 4015 閱讀 1817

####最長有效括號

給定乙個只包含 『(』 和 『)』 的字串,找出最長的包含有效括號的子串的長度。

示例 1:

輸入: 「(()」

輸出: 2

解釋: 最長有效括號子串為 「()」

示例 2:

輸入: 「)()())」

輸出: 4

解釋: 最長有效括號子串為 「()()」

dp表示0~i的有效括號子串的長度。

遇到』(『直接跳過,因為之前沒有與之匹配的括號。

遇到』)』,我們則開始進行討論,j=i-1-dp[i-1] (我們需要跳過在這之前的已經匹配的有效子串) 例如: (()()) pos=6,j=1 dp[i-1]=4.

若j處的括號是』(』,那麼狀態轉移方程為:dp=dp]+2;

我們還需要加j-1之前的有效子串。例如: () (()())

class solution 

int ans=0;

int len=s.length();

int dp=new int[len];

dp[0]=0;

for(int i=1;i=0&&s.charat(j)=='(')}}

ans=math.max(ans,dp[i]);

}return ans;

}}

#####最長上公升子串行

給定乙個無序的整數陣列,找到其中最長上公升子串行的長度。

示例:輸入: [10,9,2,5,3,7,101,18]

輸出: 4

解釋: 最長的上公升子串行是 [2,3,7,101],它的長度是 4。

說明:可能會有多種最長上公升子串行的組合,你只需要輸出對應的長度即可。

你演算法的時間複雜度應該為 o(n2) 。

高階: 你能將演算法的時間複雜度降低到 o(n log n) 嗎?

o(logn)做法:利用lower_bound

class solution 

int total=0;

int vec=new int[nums.length];

vec[total++]=nums[0];

for(int i=0;ivec[total-1])else

}return total;

}public int lower_bound(int arr,int k,int target)else

}return l;

}}

10. 正規表示式匹配
給定乙個字串 (s) 和乙個字元模式 §。實現支援 『.』 和 『』 的正規表示式匹配。

『.』 匹配任意單個字元。

'』 匹配零個或多個前面的元素。

匹配應該覆蓋整個字串 (s) ,而不是部分字串。

說明:s 可能為空,且只包含從 a-z 的小寫字母。

p 可能為空,且只包含從 a-z 的小寫字母,以及字元 . 和 。

示例 1:

輸入:s = 「aa」

p = 「a」

輸出: false

解釋: 「a」 無法匹配 「aa」 整個字串。

示例 2:

輸入:s = 「aa」

p = "a"

輸出: true

解釋: 『』 代表可匹配零個或多個前面的元素, 即可以匹配 『a』 。因此, 重複 『a』 一次, 字串可變為 「aa」。

示例 3:

輸入:s = 「ab」

p = "."

輸出: true

解釋: "." 表示可匹配零個或多個(』』)任意字元(』.』)。

示例 4:

輸入:s = 「aab」

p = 「cab」

輸出: true

解釋: 『c』 可以不被重複, 『a』 可以被重複一次。因此可以匹配字串 「aab」。

示例 5:

輸入:s = 「mississippi」

p = 「misisp*.」

輸出: false

這道題我們需要分情況討論,首先先注意一點 * 前一定是有字母的,例如 a* 就表示a可以為0個也可以為n個。

我們就要分清理討論了。

首先dp表示s串前i個與p串前j個字元的匹配情況。

如果si == pj的話,dp=dp

如果pj == '.'的話,dp=dp,同上。

接下來就要討論pj == '*'的情況了。

至於初始化,dp[0][0]表示我們兩個串還沒開始匹配,那麼肯定為true

class solution 

int n=s.length();

int m=p.length();

boolean dp=new boolean[n+1][m+1];

dp[0][0]=true;

for(int i=1;i44. 萬用字元匹配

給定乙個字串 (s) 和乙個字元模式 § ,實現乙個支援 『?』 和 『』 的萬用字元匹配。

『?』 可以匹配任何單個字元。

'』 可以匹配任意字串(包括空字串)。

兩個字串完全匹配才算匹配成功。

說明:s 可能為空,且只包含從 a-z 的小寫字母。

p 可能為空,且只包含從 a-z 的小寫字母,以及字元 ? 和 。

示例 1:

輸入:s = 「aa」

p = 「a」

輸出: false

解釋: 「a」 無法匹配 「aa」 整個字串。

示例 2:

輸入:s = 「aa」

p = ""

輸出: true

解釋: 『』 可以匹配任意字串。

示例 3:

輸入:s = 「cb」

p = 「?a」

輸出: false

解釋: 『?』 可以匹配 『c』, 但第二個 『a』 無法匹配 『b』。

示例 4:

輸入:s = 「adceb」

p = 「ab」

輸出: true

解釋: 第乙個 '』 可以匹配空字串, 第二個 '』 可以匹配字串 「dce」.

示例 5:

輸入:s = 「acdcb」

p = "ac?b"

輸入: false

這道題比上一道更加直觀,討論的情況也少很多。

首先dp表示s串前i個與p串前j個字元的匹配情況。

如果si==pj的話,dp=dp

如果pj=='.'的話,dp=dp,同上。

接下來就要討論pj=='*'的情況了。這一步是和上面一樣的。

當pj=='*'的時候,其實很直觀,*只有為空串或者匹配n個字元,而且多個字元是從s串第i個到第i+n-1個這個範圍,

不可能是這個範圍之外的串了,自己推一下就知道了。

匹配多個字元,就和上一題一樣,dp=dp,就是s串刪除乙個字元,只是上一題刪除的重複的字元,

這一題刪除的是不重複的多個字元。

接著是空串,即dp=dp,即把*刪掉,還有就是匹配乙個字元,也是dp=dp.

那麼轉移方程就是dp=dp||dp.其中一種成立即為true.

記得初始化化,即dp[0][0]不一定是開始的點,例如: ???? ?是可以為空串的。可以從dp[0][1]開始,

也可以從dp[0][2]開始,以此類推。

class solution 

int n=s.length();

int m=p.length();

boolean dp=new boolean[n+1][m+1];

dp[0][0]=true;

for(int i=1;i<=m;++i)

}for(int i=1;i<=n;++i)

if(p.charat(j-1)=='*')}}

return dp[n][m];

}}

石子合併 —區間dp

傳送門

動態規劃合集

看999,999比 1大,但dp 7 dp 5 1的,即999要和前面的1234組成最長序列,不能和 1組成最長,所以不僅要前面挑後面 a j dp i 999是合格的 後面 但 1 2是不合格的 前面 static void solve dpv i push back a i int k 1 fo...

動態規劃 常見揹包問題合集

01揹包 有n件物品和乙個容量為v的揹包。每件物品只有一件 第i件物品的費用是c i 價值是v i 求解將哪些物品裝入揹包使總價值最大。轉移方程 f i v max,可以優化只用一維陣列.如下 for int i 0 i w i j if record j c i v i record j reco...

動態規劃 什麼是動態規劃?

先來看看 資訊學奧賽一本通第5版 是怎麼說的 動態規劃程式設計是對解最優化問題的一種途徑 一種方法,而不是一種特殊演算法。不像前面所述的那些搜尋或數值計算那樣,具有乙個標準的數學表示式和明確清晰的解題方法。動態規劃程式設計往往是針對一種最優化問題,由於各種問題的性質不同,確定最優解的條件也互不相同,...