標籤:style class blog code tar color
Given a string containing just the characters ‘(‘ and ‘)‘, find the length of the longest valid (well-formed) parentheses substring.For "(()", the longest valid parentheses substring is "()", which has length = 2.Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.
Analysis: 這道題真是讓我想了很久,之前做過的有關Parentheses的題目都沒有遇到這種難度的。真是體會到好的演算法抵過千萬行代碼啊。我嘗試了幾種方法:
1. Naive Solution: 遍曆String的所有substring, 選取最長的matched substring, 不用說,這種做法的複雜度為O(N^3),絕對是不可能通過OJ的大case測試的,一定會TLE
2. 把String中所有的‘(’ 作為 start, 因為我們知道matched string一定是以 ‘(’ 開始的。由這個 start開始尋找最長的matched string,這樣做的時間複雜度為O(N^2), 我依然知道不是最優的,肯定有O(N)的演算法
3. DP方法,這個想法並不成熟,就是從尋找一個最基本的配對單元 ‘()‘開始,逐步遞推。isValid[i][j]表示從i到j是否是一個valid的運算式。isValid[i][j]為真的條件可以遞推。這個想法太過艱深,沒有深入
4. 想到了用Stack的方法,結果因為其中一個細節想不出來該怎麼處理而放棄了。這個細節是:比如S是()(())),最長的matched substring是 ()(()), 可是用stack能檢查到(),能檢查到(()),但是如何檢查到它們一起?我當時不知道怎麼辦了。後來查看了網上的解答,發現別人也用Stack,做法令人歎為觀止,很好地解決了我的這個問題。下面會講:
於是我貼上參考了網上別人解答以後我用stack的解法吧:
Solution Analysis: 遍曆S。遇到‘(‘,放入lefts。如果遇到‘)‘,如果lefts是空,說明這是一個無法匹配的‘)‘,記錄下last。last裡面存放的其實是最後一個無法匹配的‘)‘。為啥要儲存這個值呢?主要是為了計算後面完整的運算式的長度。可以這樣理解: “所有無法匹配的‘)‘”的index其實都是各個group的分界點。這樣做非常好地解決了我之前說的那個如何檢驗()(())的問題。如果lefts不是空,說明棧內還有‘(‘, 一個最外層完整的group還沒有匹配完成,但是怕後面S沒有更多元素了,所以需要計算當前已經完整部分運算式的長度,有可能把它用作maxlen。
1 public class Solution { 2 public int longestValidParentheses(String s) { 3 int Maxlen = 0; 4 int lastleft = -1; 5 Stack<Integer> lefts = new Stack<Integer>(); 6 for (int i = 0; i < s.length(); i++) { 7 if (s.charAt(i) == ‘(‘) { //new element is ‘(‘ 8 lefts.push(i); 9 }10 else { //new element is ‘)‘11 if (lefts.empty()) { // ‘)‘ is not matched, denote this index, as a dividing node12 lastleft = i;13 }14 else { // ‘)‘ is matched15 lefts.pop();16 if (lefts.empty()) { // no more ‘(‘ left in Stack lefts17 Maxlen = Math.max(Maxlen, i - lastleft);18 }19 else {20 Maxlen = Math.max(Maxlen, i - lefts.peek());21 }22 }23 }24 }25 return Maxlen;26 }27 }