1. 程式人生 > 其它 >leetcode 32 最長的括號

leetcode 32 最長的括號

題目連結

本題的難點:剛開始想的話是想用棧匹配的方式來貪心的求解,後面發現"((())(()"這種形式的串貪心的話會將後面部分的算入答案中得到錯誤結果。那麼問題就變成了一個遞推式的問題,我們可以使用函式遞迴的思想來想,假設一個位置i處的左端左括號的數量已經大於右端,然而此時右端的答案並不能直接算進答案之中,因為不知道左端的括號是否能夠全部被後面右端的右括號給匹配上,因此只有當左端最後一個括號被匹配上的時候,才能遞迴的處理左端之前已經匹配上的括號,時間複雜度大概是\(O(N^2)\),這是無法接受的=.=
此時應該用動態規劃求解,\(dp[i]\)表示當前位置左端的最大合法匹配長度,易得"("處的值應該全部都是0,對於右括號,我們分為兩種情況:

  • \(s[i-1]\)為左括號的時候,我們可以知道此時剛好得到了一對新的匹配,所以此時的\(dp[i]=dp[i-2]+2\)
  • \(s[i-1]\)為右括號的時候,如果\(s[i-1]\)處的右括號也有自己的匹配,我們此時就可以回溯到\(s[i-1]\)最大匹配長度的左端,也就是\(i-dp[i-1]-1\)處,如果此處符號為左括號,那麼剛好和當前\(s[i]\)位置的右括號匹配上,我們可以新得到一段從\(i-dp[i-1]-1\)\(i\)處的合法匹配。注意此時沒有結束,假設\(i-dp[i-1]-1\)左端還有合法匹配呢?,所以此時得到新的遞推方程\(dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]\)

程式碼如下

class Solution {
public:
    int longestValidParentheses(string s) {
        int n=s.size();
        vector<int> dp(n+1,0);

        int ans=0;
        for(int i=1;i<n;i++){
            if(s[i]==')'){
                if(i>1&&s[i-1]=='(') dp[i]=dp[i-2]+2;
                else if(i-dp[i-1]>0&&s[i-dp[i-1]-1]=='('){
                    dp[i]=dp[i-1]+2+((i-dp[i-1])>=2?dp[i-dp[i-1]-2]:0);
                }
            }
            ans=max(ans,dp[i]);
        }
        return ans;
    }
};