記錄技巧。
有三種解法,比較想記的是後兩種,尤其是第二種。
第一種:
暴力求解
枚舉每個‘(’,用棧或者給’(’’)'賦值成-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。