給定乙個只包含 '(' 和 ')' 的字串,找出最長的包含有效括號的子串的長度。
示例 1:
輸入: "(()"
輸出: 2
解釋: 最長有效括號子串為 "()"
示例 2:
輸入: ")()())"
輸出: 4
解釋: 最長有效括號子串為 "()()"
定義 dp[i] 表示以下標 i 字元結尾的最長有效括號的長度。
1.當s[i-1]=='(' && s[i]==')'時,即字串形如"...()"時
dp[i]=dp[i-2]+2
2.當s[i-1]==')' && s[i]==')'時,即字串形如"...))"時
(這個情況很複雜,詳細分析)
2.1觀察這個括號串0
1234
567(
((()
)))我們希望計算 dp[7] 的值
已知1~6是有效的括號串,所以 -- 條件1: dp[6]==6; 條件2: s[7 - 6 - 1] 即 s[0] == '('
所以 dp[7] = dp[6] + 2 = 8
所以
if( s[i - dp[i-1] - 1] == '(' )
012
3456
7)((
()))
)已知1~6是有效的括號串,所以 -- 條件1: dp[6]==6; 條件2: s[7 - 6 - 1] 即 s[0] == ')'
因為條件2 s[0] = ')' ; 所以 dp[7] = 0
然而實際上沒有這麼簡單!!! 在情況2.1的基礎上,還有一種高階情況!!
2.2觀察這個括號串0
1234
5678
91011(
((()
)))(
())我們希望計算 dp[11] 的值
按照前文的情況2.1,
條件1: dp[10]==6; 條件2: s[11 - 2 - 1] 即 s[8] == '('
所以 dp[11] = dp[10] + 2 = 4
上面這個"遞推結果"是錯誤的
為什麼?
我發現,
dp[10]對應 "9~10這2個格仔"
dp[11]在dp[10]的基礎上,向左右兩邊都拓展了一格, 即"8~11這4個格仔"
向左拓展一格對應於 情況2.1 中的這個判斷:
s[i - dp[i-1] - 1] == '('
向右拓展一格對應於
s[i] = ')' 即我們正在求解的這一格
由於向左拓展了一格, 8號格仔和前面的7號格仔相連起來了~~~~
所以,我還需要把 dp[7] 計算在內
假如,7號格仔是"某一有效括號串的結尾字元"
dp[11] = dp[10] + 2 + dp[7]
假如,7號格仔不是"某一有效括號串的結尾字元"
dp[11] = dp[10] + 2 + 0
可以寫出如下偽**
if( dp[i - dp[i - 1] - 2] > 0 )
if( dp[i - dp[i - 1] - 2] == 0 )
//精簡後實際上只需要一行
為什麼要畫遞迴樹?因為所謂"遞迴樹"就是一種自頂向下分析問題的思路圖
動態規劃就是自頂向下分析,自底向上求解,所以做動態規劃一定要畫出遞迴樹
就算已經推導出了狀態轉移方程,仍然需要畫出遞迴樹排查有無思維漏洞!!!!!
遞迴樹可以很直觀地看出動態規劃的重疊子問題
有效的括號串一定以 ')' 結尾
所以 '(' 字元結尾的括號串有效長度移動為0,即
if(s.charat(i)=='(')
我設定的邊界條件出錯了,實話說我不知道錯在哪
public class solution
public int longestvalidparentheses(string s)
//遞迴樹的"....))"分支
else if(s.charat(i-1)==')'&&s.charat(i)==')')}}
}maxans = math.max(maxans, dp[i]);
}return maxans;
}public static void main(string args)
}
實際編碼的時候和思路的時候不一樣
解題思維分幾個過程
1.紙上演算法推演
2.書寫偽**
3.實際編碼
1.紙上演算法推演時,只是形成"人類可讀"的演算法思路
2.書寫偽** 已經開始關注"如何用**表述演算法"但是對於"陣列越界,指標越界等"仍然缺乏**
3.實際編碼要考慮到一切,比如陣列越界等
dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
//加上"三元算符"是為了防止i - dp[i - 1] - 2處位於陣列頭部,防止陣列從起始處越界
class solution
//遞迴樹的"....))"分支
else if(s.charat(i-1)==')'&&s.charat(i)==')')}}
}maxans = math.max(maxans, dp[i]);
}return maxans;}}
LeetCode 32 最長有效括號
思路 自己沒想出來,參考了一下網上大神的提示。使用乙個int棧,將左括號記為 1,右括號記為 2 遍歷字串。1.若為 則直接壓入棧 2.若為 分情況討論 若棧頂為 2 或棧空,則直接將 2壓入棧 若棧容量為1,且棧頂為 1,將 1推出棧,推入2,代表此時有一對匹配括號 若棧容量為1,且棧頂大於0,說...
leetcode 32 最長有效括號
一 先對字串進行遍歷 首先從前往後排除不配對的 首次遍歷後的字串被分成若干個字串 再對這些字串 從後往前排除不配對的 int longestvalidparentheses std string s else if s j else t1 j 1 n 0 continue if max2 n max...
LeetCode32 最長有效括號
題目鏈結 500 800ms class solution else if s j for int i 0 ilength i if s i 0 result 0 if result k return result else return k 這絕不是最優解 幾十毫秒之內解決問題 class sol...