最长有效括号

时间:2022-07-22
本文章向大家介绍最长有效括号,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

问题描述:

给定一个只包含 '('')' 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:

输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

大体思路:

定义dp[i] 为以 i 结尾的最长有效括号长度。

转移函数如下:

dp[i] = begin{cases}0 qquad qquad qquad qquadqquad qquadqquad qquadqquad qquad s[i] = ‘(‘\ dp[i - 2] + 2 qquad qquadqquad qquadqquad qquad s[i] = ‘)’,s[i - 1] = ‘(‘ \ dp[i - 1] + 2 + dp[i - dp[i - 1] - 2] qquad s[i] = ‘)’,s[i - 1] = ‘)’,s[i - dp[i - 1] - 1]= ‘(‘ \ 0 qquad qquadqquad qquadqquad qquadqquad qquadquad s[i] = ‘)’,s[i - 1] = ‘)’,s[i - dp[i - 1] - 1]= ‘)’ end{cases}

为了简化逻辑,上述公式并未考虑溢出的情况。

第一种情况当前结点为左括号,以其结尾无论如何也构不成有效括号,值为0;

第二种情况,形如“(())()”的当前结点为最后一个元素的情况,当前结点为右括号,前一个为左括号,其正好能组成一对,因此等于i - 2结尾的长度加2;

第三种情况形如“()(()())”的当前结点为最后一个元素的情况,当前结点为右括号,其前一个结点也为右括号,s[i - dp[i - 1] - 1]为以s[i - 1]结尾的最长有效括号的前一个元素,该元素为左括号时就可以和s[i]的右括号组成一对,因此结果为dp[i - 1] + 2 + dp[i - dp[i - 1] - 2]。

第四种情况形如“)()())”的当前结点为最后一个元素的情况,s[i - dp[i - 1] - 1]不能和s[i]组成一对,因此以当前结点结尾的最长有效长度为0。

实现代码如下:

class Solution {
    public int longestValidParentheses(String s) {
        int N = s.length();
        int[] dp = new int[N];
        int max = 0;
        for(int i = 1; i < N; i++){
            if(s.charAt(i) == '('){
                continue;
            }
            if(s.charAt(i - 1) == '('){
                dp[i] = i - 2 < 0 ? 2 : 2 + dp[i - 2];
            }else if(i - dp[i - 1] - 1 >= 0 && s.charAt(i - dp[i - 1] - 1) == '('){
                dp[i] = dp[i - 1] + 2;
                dp[i] += i - dp[i - 1] - 2 < 0 ? 0 : dp[i - dp[i - 1] - 2];
            }
            max = Math.max(max, dp[i]);
        }
        return max;
    }
}