LeetCode解題報告—— Longest Valid Parentheses
Given a string containing just the characters ‘(‘
and ‘)‘
, find the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"
Example 2:
Input: ")()())
" Output: 4 Explanation: The longest valid parentheses substring is"()()"
思路
嘗試遍歷判斷所有組合結果超時,想到了用dp來解這題卻不知道怎麽來建模,還是經驗少了。
看了下解答,有多種解法,首先是dp。看了之後發現為什麽自己的dp總是建不起來了,首先是確定一維的dp還是二維的dp,這題的變量有兩個,一個是字符串的長度,還有就是最優解也就是最長合法parentheses substring的長度,那麽用一維的dp數組dp[i]即可。接下來確定的是dp[i],中索引的 i 具體指的是什麽,在考慮這步的時候我沒有想清楚,與其說 i 具體指什麽倒不如說我們要賦給 i 的意義是什麽,我原來的想法是 i 代表從0到i的字串,這樣來代表子問題,比如dp[5]表示的是從索引0到5的字串中最長合法 parentheses substring 的長度,dp[10] 表示從索引0到10的字串中最長合法 parentheses substring 的長度等。然後依次去探究遞推公式時(問題與其相鄰子問題的關系)卻發現很不好找,因為
假如在 i 位置和 i-1 位置上的 字符是 ( 和 ),構成一對合法,但是還是確定不了 dp[i] 和 dp[i-2] 的關系,因為確定不了dp[i-2] 中的合法字符是不是在末尾 i-2 處終結的,如果是的話則dp[i]=dp[i-2]+2,否則不能確定判斷是否加2。
上面的dp建模思路之所以不正確是因為建模沒有清楚問題,或者說是限定問題,也可以說是建模對於問題的描述存在不清楚,不明確的地方。比如對於 dp[i] 雖然可以由此知道子串的最長合法字串的長度,但是由於這題是括號匹配,故子串中括號字符串出現的位置是很重要的,而dp[i]雖然可以確定 子問題的最優解,子問題中字符串的長度這兩個變化的要素,但是卻確定不了合法括號字符串在字串中出現的位置,所以導致實際解題時思路異常困難,因為本身的模型就有問題。
正確的 dp[i] 建模是這樣的,值肯定是最長合法括號字符串的長度,而這個 i 代表的是以i位置為結束的最長合法字串,即dp[5]表示的是索引0到5的字符串中以索引5(末尾)為結束的最長的合法字串的長度。這樣便能很方便的確定問題與相鄰子問題之間的數學關系。
第二個可能有點難理解,因為 dp[i] 表示的是以索引 i 處為結束的最長合法字串的長度,那麽它前一個字符的位置便是 i - dp[i]-1, 如果這個位置 是 ( 那麽可能和新加入的 ) 構成合法,因為這個 ( 之前的字符串也可能是合法的,所以要在一起算。
只考慮以上的情況是因為如果以(( 或者)( 的話,以 ( 在末位置結束的肯定是非法,dp數組的是0.
代碼
public class Solution {
public int longestValidParentheses(String s) {
int maxans = 0;
int dp[] = new int[s.length()];
for (int i = 1; i < s.length(); i++) {
if (s.charAt(i) == ‘)‘) {
if (s.charAt(i - 1) == ‘(‘) {
dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;
} else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == ‘(‘) {
dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;
}
maxans = Math.max(maxans, dp[i]);
}
}
return maxans;
}
}
剩下的方式有兩種,Using Stack 和 Without extra space: https://leetcode.com/problems/longest-valid-parentheses/solution/
LeetCode解題報告—— Longest Valid Parentheses