LeetCode Longest Valid Parentheses 括号匹配

括号匹配问题一般的处理方式有两种:①使用栈的push/pop模拟;②给括号赋予正负的分值(+1/-1),从左到右计算分数之和。一个合法的串中任意位置的分数不会小于0(左括号数大于等于右括号)。

题意:给定一个由“(”和")"组成的字符串,求最长合法子串的长度。

栈一般用来判定括号序列是否合法,这里使用第二种方法。从左到右扫描一遍,遇到分数小于0则跳过该位置,从下一个位置起继续向右扫描,遇到分数为0的位置时则更新结果,处理代码如下:

int l = 0, r = 0, sum = 0;
int ans1 = 0;
while(r < len){
    sum += s[r] == '(' ? 1 : -1;
    if(sum < 0){
        l = r + 1;
        sum = 0;
        }
    else if(sum == 0){
        if(r - l + 1 > ans1)
            ans1 = r - l + 1;
    }
    ++r;
}

但我们仅仅只能排除掉不合法的位置,获得“局部最优解”,最后剩下的串中左括号的数目可能大于右括号(最容易想到的情况是:起点处左括号刚好冗余),所以最优解可能包含在剩下的串中未进行更新。这种情况怎么处理呢?换个方向想一想,从左到右扫描,左括号的数目大于等于右括号;反过来,从右到左扫描,右括号的数目大于等于左括号,否则序列非法。所以对于剩下的串,只需从右往左扫描一次,就可以找出包含在其中的合法序列。

设从左到右扫描时,最后的待定串为,则定有:中任意位置处的分数都大于0,否则该位置要么被跳过、要么被更新。设中最后一个')'的位置为,则对所有。则从右往左扫描时,这些都会被跳过,然后从开始进行计算,对其他位置同理。这是因为,从左到右中任意位置的左括号大于右括号数,而这在从右往左扫描时,是非法的,这些非法的位置会被跳过,而合法的位置则会被更新。所以最后能得到正确的结果。代码如下:

class Solution {
public:
    int longestValidParentheses(string s) {
        int len = s.size(), i = 0, j = len - 1;
        int l = 0, r = 0, sum = 0;
        int ans = 0;
        while(r < len){
            sum += s[r] == '(' ? 1 : -1;
            if(sum < 0){
                l = r + 1;
                sum = 0;
            }
            else if(sum == 0){
                if(r - l + 1 > ans)
                    ans = r - l + 1;
            }
            ++r;
        }
        int bound = l;
        r = len - 1, l = len - 1, sum = 0;
        int tmp = 0;
        while(l > bound){
            sum += s[l] == '(' ? 1 : -1;
            if(sum > 0){
                r = l - 1;
                sum = 0;
            }
            else if(sum == 0){
                if(r - l + 1 > tmp)
                    tmp = r - l + 1;
            }
            --l;
        }
        return ans > tmp ? ans : tmp;
    }
};


你可能感兴趣的:(LeetCode)