letcode32最長有效括號

記錄技巧。


有三種解法,比較想記的是後兩種,尤其是第二種。

第一種:

暴力求解
枚舉每個‘(’,用棧或者給’(’’)'賦值成-1和1的方式遍歷過來,找到那個最長的即可。
時間複雜度爲n^2,空間複雜度爲n,也可以是1。這裏很簡單,不細寫了。

第二種:

給每個元素標上對應的下標值。
純思路是用棧來配對’(‘和’)’,並利用他們的下標之差計算匹配成功的長度。
然後找到最長的。
然後我就開始模擬,然後出現了各種情況,一言難盡,當然我覺得直接模擬肯定是可行的,但我還是選擇了找找高明的做法。於是就看到了大佬的方法。
開一個棧,先給他入上第一個值-1。這個壓入-1的手法太高明瞭。
遇到’(‘就入棧
遇到‘)’就彈出棧頂,棧頂彈出之後,然後此時遇到的‘)’的下標與新棧頂的值做差,這時的查就是這輪的長度。但如果發現新棧頂的值是-1,那需要彈出-1,再把此時’)'的下標壓入棧內。
那爲什麼要這麼操作呢?
看看代碼,再畫幾個樣例就自然明白了。

class Solution {
public:
    int longestValidParentheses(string s) {
        int len = s.size(), mi=0;
        stack<int> st;;
        st.push(-1);
        for(int i=0; i<len; i++){
            if(s[i]=='('){
                st.push(i);
            }
            else{
                st.pop();
                if(st.empty()){
                    st.push(i);
                }
                else{
                    mi = max(mi, i-st.top());
                }
            }
        }
        return mi;
    }
};

很喜歡這種做法,唯一不足的就是他的空間複雜度是n,時間複雜度也是n。
時間複雜度倒是無法再優化了,空間複雜度還可以再優化。

第三種:

從左到右或從右往左遍歷
遍歷的時候記錄下‘(’和’)'各自出現的次數。
比如正向遍歷時,
當兩者出現次數相等時說明兩着匹配,此時記錄一下,當右括號多餘左括號時,說明這個多出來的右括號不可能會在後面被匹配,此時將兩者次數都置零。重複這個操作,此間記錄最大值。

然後我就直接很快的擼出了代碼,但是發現有情況沒有考慮到,
比如:()(()()
這種中間被一個多出來的’('給斷開的無法找出正確答案。
怎麼辦呢
再逆向遍歷一次。

class Solution {
public:
    int longestValidParentheses(string s) {
        int len = s.size(), mi=0, mm = 0, l=0, r=0;
        for(int i=len-1; i>=0; --i){
            if(s[i]=='(')  l ++;
            else    r ++;
            if(l>r) l=0, r=0;
            if(l==r) mi=max(mi, r*2);
        }
        l = 0, r=0;
        for(int i=0; i<len; ++i){
            if(s[i]=='(')  l ++;
            else   r ++;
            if(l<r) l=0, r=0;
            if(l==r) mm=max(mm, r*2);
        }
        return max(mm, mi);
    }
};

時間複雜度爲n,空間複雜度爲1。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章