題目鏈接: https://leetcode.com/problems/longest-valid-parentheses/description/
Description
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.
解題思路
整體思路爲動態規劃,用數組 dp[i]
記錄以 s[i]
爲最後一個字符的最長合法括號長度。
首先可以想到,合法的括號要包括 (
和 )
,因此遍歷字符串時,若遇到 (
時可以暫時不管,僅當遇到 )
時再來處理。另外,合法的括號主要有兩種形式:
()() => s[i] == ')' and s[i - 1] == '('
(()) => s[i] == ')' and s[i - 1] == ')'
先考慮第一種形式,容易想到只需要將 s[i - 2]
爲最後一個字符的最長合法括號長度加 2 即可,即 dp[i] = dp[i - 2] + 2
第二種形式稍微複雜一點點,需要定位 s[i]
對應的另一個左括號 (
的位置。因爲 dp[i - 1]
記錄了以 s[i - 1]
爲結尾的最長合法括號長度,那麼顯然 i - dp[i - 1] - 1
就應該是 s[i]
對應的另一個左括號應該在的位置,dp[i - 1]
就是夾在這對外括號中間的最長合法括號長度。要計算 dp[i]
的話,還要考慮緊挨着這對外括號左側的最長合法括號長度,因爲子串可能爲 "()(())"
,因此這種情況 dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2]
對於爲什麼 i - dp[i - 1] - 1
是 s[i]
對應的另一個左括號的位置,舉個簡單的例子看下。s = "(())"
,當遍歷完前三個字符後 dp[] = {0, 0, 2, x}
,x
表示未知。此時來計算最後一個字符 s[3]
對應的 dp[3]
的值,可以看到 s[3]
對應的左括號應該就是下標爲 i - dp[i - 1] - 1 = 3 - dp[2] - 1 = 0
的字符 s[0]
。
時間複雜度 O(n)
,空間複雜度 O(n)
,n
爲字符串 s
的長度。
Code
class Solution {
public:
int longestValidParentheses(string s) {
int maxLen = 0;
vector<int> dp(s.size());
for (int i = 1; i < s.size(); ++i) {
if (s[i] == ')' && s[i - 1] == '(') {
dp[i] = i > 1 ? dp[i - 2] + 2 : 2;
} else if (s[i] == ')' && s[i - 1] == ')' && s[i - dp[i - 1] - 1] == '(') {
if (i - dp[i - 1] - 2 >= 0)
dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2];
else
dp[i] = dp[i - 1] + 2;
}
maxLen = max(dp[i], maxLen);
}
return maxLen;
}
};