最长有效括号(dp/栈/计数)

题目:https://leetcode-cn.com/problems/longest-valid-parentheses/
参考了官方orz
dp做法: d p [ i ] dp[i] 表示前 i i 个字符能得到的最大长度

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.length();
        vector<int> dp;
        dp.resize(n+1);
        int ans = 0;
        for(int i = 1;i < n;i++) {
            if(s[i] == ')') {
                if(s[i-1] == '(')
                    dp[i] = (i >= 2 ? dp[i-2] : 0) + 2;
                else if(i-1-dp[i-1] >= 0 && s[i-1-dp[i-1]] == '(')
                    dp[i] = dp[i-1] + (i-2-dp[i-1] >= 0 ? dp[i-2-dp[i-1]] : 0) + 2;
                ans = max(ans,dp[i]);
            }
        }
        printf("%d\n",ans);
        return ans;
    }
};

栈做法

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.length();
        stack<int> st;
        int ans = 0;
        st.push(-1);
        for(int i = 0,x;i < n;i++) {
            if(s[i] == '(') st.push(i);
            else{
                st.pop();
                if(st.empty()) st.push(i);
                else ans = max(ans,i-st.top());
            }
        }
        printf("%d\n",ans);
        return ans;
    }
};

更精简做法,用 l l 记录左括号数,用 r r 记录右括号数,从左到右遍历,当 l = = r l==r 时更新答案;再从右到左遍历一遍。
正确性证明:我们在从左到右遍历时,会漏掉统计的情况就是 l > r l>r 的情况,如 ( ( ( ) ) ((()) ,而这确是从右到左遍历会考虑到的。这两种遍历相辅相成,考虑了所有的情况。

class Solution {
public:
    int longestValidParentheses(string s) {
        int n = s.length();
        int l = 0,r = 0;
        int ans = 0;
        for(int i = 0;i < n;i++) {
            if(s[i] == '(') l++;
            else r++;
            if(l == r) ans = max(ans,2*l);
            else if(l < r) l = r =0;
        }
        l = 0,r = 0;
        for(int i = n-1;i >= 0;i--) {
            if(s[i] == '(') l++;
            else r++;
            if(l == r) ans = max(ans,2*l);
            else if(l > r) l = r =0;
        }
        printf("%d\n",ans);
        return ans;
    }
};
发布了71 篇原创文章 · 获赞 1 · 访问量 2796

猜你喜欢

转载自blog.csdn.net/weixin_43918473/article/details/104332928