1. 程式人生 > >LeetCode解題報告—— Longest Valid Parentheses

LeetCode解題報告—— Longest Valid Parentheses

自己 con ali and ini longest else 合法括號 說我

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