LeetCode 32. Longest Valid Parentheses

DP

由于括号匹配的特殊性,合法的括号匹配最后一定是')',因此我们可以记录以每个字符为结尾的最长括号匹配数。

dp[i] = 以s[i]结尾的最长括号匹配数

递推公式有两种可能:

1. 如果s[i-1]=='(',dp[i] = dp[i-2] + 2

2. 如果s[i-1]==')',我们可以通过 dp[i-1] 找到以 s[i-1] 结尾的最长字符串,我们只需判断前一个字符 s[i-dp[i-1]-1] 是不是'(',如果是,那么 dp[i] = dp[i-dp[i-1]-2] + dp[i-1] + 2

base: dp[0] = 0

target: max dp[i]

当然dp的递推公式也可以把两种情况合并,因为如果 s[i-1]=='(', dp[i-1]一定为0,可以整合进公式。

整个流程非常类似 Kadane's algorithm。

class Solution {
public:
    int longestValidParentheses(string s) {
        int n=s.size();
        int res=0;
        vector<int> dp(n,0); // longest valid parentheses ending at index i
        for (int i=1;i<n;++i){
            if (s[i]==')'){
                if (s[i-1]=='(')
                    dp[i] = (i-2>=0 ? dp[i-2] : 0) + 2;
                else if (s[i-1]==')' && i-dp[i-1]-1 >= 0 && s[i-dp[i-1]-1]=='('){
                    dp[i] = (i-dp[i-1]-2>=0 ? dp[i-dp[i-1]-2] : 0) + dp[i-1] + 2;
                }
                res = max(res, dp[i]);
            }
        }
        return res;
    }
};

时间复杂度 O(n)

 

Stack

括号的题stack也是一种解题思路。我们可以用stack来抵消匹配的括号,问题是如何找到匹配括号的长度。

思路类似 LeetCode 42. Trapping Rain Water 的stack解法中的left,本题里 i-st.top() 就是当前')'结尾的最大长度。

我们需要往stack里事先加入一个-1,并且每次pop导致stack为空的话,我们需要将当前元素加入stack。

如 ()() ,到第二个'('时,stack里是 -1, 2,第二个')'会pop掉2,3-(-1)=4 就是当前最大长度。

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

时间复杂度 O(n)

 

posted @ 2019-10-15 04:38  約束の空  阅读(118)  评论(0编辑  收藏  举报