給你乙個只包含 '(' 和 ')' 的字串,找出最長有效(格式正確且連續)括號子串的長度。
示例 1:
輸入:s = "(()"
輸出:2
解釋:最長有效括號子串是 "()"
示例 2:
輸入:s = ")()())"
輸出:4
解釋:最長有效括號子串是 "()()"
示例 3:
輸入:s = ""
輸出:0
0 <= s.length <= 3 * 104
s[i] 為 '(' 或 ')'
本題有三種解法,分別是動態規劃法,棧法和兩次遍曆法。
動態規劃法比較難想,我們使用乙個dp陣列來記錄有效括號的長度,對於「(」來說,可以形成的有效括號總為0,因為需要有右括號才能形成有效括號。對於「)」來說,需要考慮三個部分,首先是對於第i個位置的右括號,需要判斷第i - dp[i - 1] - 1的位置是否為左括號,如果不是左括號,那麼就無法構成有效括號,dp[i] = 0,如果是,則有效括號長度可以+2,這個時候考慮第i個括號內部的長度,所以dp[i] += dp[i - 1],最後,我們還得考慮第i個括號對應的左括號前面有效括號的長度,所以dp[i] += dp[i - dp[i - 1] - 1],所以,遞推公式為dp[i] = dp[i - dp[i - 1] - 1] + dp[i - 1] + 2(假設三個部分都為有效括號)
棧法和括號匹配的棧方法規則不太一樣,提前將棧加入-1,方便邊界處理,對於"("來說,入棧就可以了,對於")"來說,如果棧頂元素是-1或者是")"那麼這個右括號是無效的括號直接入棧,如果棧頂元素是"("那麼直接將棧頂出棧,這個右括號對應的最長有效括號長度就為這個右括號的下標減去了現在的棧頂元素。
雙向遍曆法其實才是剛剛開始想到的乙個,只不過剛剛開始只想到了單向遍歷,可以使用left 和right同時記錄左右括號的個數,如果left = right 說明是有效括號,將其長度與最長長度比較並記錄,如果left < right說明當前括號非法,將left與right全部置0,但是有個問題是這種方法容易漏掉"(()"這種情況,在這種情況下,left和right永遠不能相等,這個時候可以從右往左再來一次遍歷,操作方法和之前遍歷類似,那麼從右往左的遍歷將漏掉"())"的情況,將兩種遍歷結合起來,就可以覆蓋所有情況了。
動態規劃法:
class棧法:solution
else
else}}
}for(auto iter : dp)
max =max(max, iter);
return
max;}};
class兩次遍曆法:solution
else}}
return
imax;}};
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...