1. 程式人生 > >LeetCode 32 Hard 最長合法括號對 Python

LeetCode 32 Hard 最長合法括號對 Python

def longestValidParentheses(self, s):
    """
    Solution Method
    演算法:動規
    思路:
            我一開始想的是和最長迴文子串一樣,用一個二維陣列dp[i][j]來記錄到s[i:j+1]部分是不是valid括號
        就像迴文子串一樣用動規陣列記錄valid情況,而不是直接記錄最長的子串長。這樣的話還是要ON2K,ON2是因為
        要兩層for,k是因為,在判斷諸如"(()())"這樣的情況時,我需要一個變數k去遍歷這個substring判斷會不會
        在某個位置k使得dp[i][k]和dp[k+1][j] 都是True,如果有的話就說明dp[i][j] == T,這樣時間複雜度還是
        沒有下來
            題解的這種解法也算是比較巧妙了,直接用一維陣列記錄第i個位置結尾的最長子串的長度
            顯然只有第i個位置是")"的時候,才可能在該位置形成合法串,然後先看i-1,如果i-1是'('的話,那麼顯然
        dp[i] = dp[i-2]+2,就是在前面的基礎上再加2這樣
            否則如果i-1的字元也是')'的話,就應該根據dp[i-1]找到前一個位置形成子串的最長的左側的那個'(',
        這個位置是i-dp[i-1],前一個字元就是k = i-dp[i-1]-1,如果k是'('的話,那麼如果dp[i] = dp[i-1]+2+before
        before就是dp[k-1]的情況,把前面的加起來補上
    """
    if len(s) < 2:
        return 0
    ans = 0
    dp = [0] * len(s)
    for i in range(1, len(s)):
        if s[i] == ')':
            if s[i - 1] == '(':
                dp[i] = dp[i - 2] + 2
            elif s[i - 1] == ')' and i - dp[i - 1] > 0:
                k = i - dp[i - 1] - 1
                if s[k] == '(':
                    before = dp[k - 1] if k >= 2 else 0
                    dp[i] = dp[i - 1] + 2 + before
        ans = max(ans, dp[i])

    return ans


def longestValidParentheses1( s):
    """
    Solution method 2
    演算法:棧
    思路:
        用棧來維護合法的括號對位置,在匹配的過程中就記錄下來最長的括號對
        匹配的過程就和普通的驗證一樣,左括號入棧,右括號來的時候出棧,匹配
        這裡棧內的棧頂表示的是【當前合法左括號的起始位置】!所以棧記憶體的是下標
            在遍歷過程中,用i-top,即i-stack[-1]來計算合法的括號長度,0,1,1-0要+1才等於2,
        所以先在棧記憶體一個數字-1,保障當出現()這樣的括號時,是能根據棧頂stack[-1] = -1 計算出長度1-(-1) = 2
            然後還是左括號入棧,右括號來了,如果棧不空,出棧,計算長度,如果棧空的話,將右括號的位置入棧,此時
        就相當於是記錄下了合法左括號前的那個位置,就像上面提到的0,1,0前面的-1一樣,從而保障能用i-stack[-1]
        獲得當前最長的子串的起始位置,然後一減就是長度
            多想想這個例子就通了"()((()))",'()))()()'
            
        """
    if len(s) < 2:
        return 0
    stack = [-1]
    ans = count = 0
    for i in range(len(s)):
        if s[i] == '(':
            stack.append(i)
        else:
            stack.pop()
            if not stack:
                stack.append(i)
            count = i - stack[-1]
            if count > ans:
                ans = count
    return ans