LeetCode-Longest Valid Parentheses

本文探讨了如何通过动态规划求解最长有效括号子串问题。介绍了算法的基本思路及其实现过程,针对不同情况讨论了状态转移方程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法分析与设计,第19周博客

32Longest Valid Parentheses

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

For "(()", the longest valid parentheses substring is "()", which has length = 2.

Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

给出一个只包含左括号 '(' 和右括号 ')' 的字符串,要求出其中最长的括号匹配的子串的长度。

关于括号匹配的问题,一般都可以用stack来解决,这题也一样,不过,在这里,并不介绍使用stack解决的方法,而是给出动态规划的解决方法。

构造这样一个dp数组,其中dp[i] 表示以s[i]结尾的最长合法括号的长度,那么,这样得出整个dp数组后,只需遍历一次就可以得出其中最大的值,也就是题目的最长合法子串的长度。

当s[i] == '(',也就是子串以左括号结尾时,这时的子串是不合法的,所以dp[i] = 0;

当 s[i] == ')',子串以右括号结尾,有可能是合法的,但是具体是否合法,以及相应的长度还与之前一个字符有关:

  1. s[i-1] == '(',此时,s[i-1] 和s[i]匹配,所以以s[i]结尾的子串存在合法匹配,再把这两个字符之前的匹配长度相加就得到了当前的长度,dp[i] = 2+dp[i-2];
  2. s[i-1] == ')',此时,需要把到s[i-1]为止的子串都剔除,再进一步判断之前的那个字符是否是左括号,从而判断是否合法并进一步计算其长度。设剔除完s[i-1]的前缀子串后的第一个字符的下标是left,那么,如果s[left] == '(',那么有 dp[i] = 2+dp[i-1]+dp[left-1];
所实现的代码如下:

class Solution {
public:
    int longestValidParentheses(string s) {
        int longest = 0, cur = 0, left = 0;
        int n = s.length();
        vector<int> dp(n+1, 0);
        for (int i = 0; i < n; ++i) {
            if (s[i] == ')' && i > 0) {
                if (s[i-1] == '(') {
                    dp[i] = i < 2 ? 2 : 2+dp[i-2];
                    longest = max(longest, dp[i]);
                } else {
                    left = i-dp[i-1]-1;
                    if (left >= 0 && s[left] == '(')
                    {
                        dp[i] = left > 0 ? 2+dp[i-1]+dp[left-1] : 2+dp[i-1];
                    }
                }
                longest = max(longest, dp[i]);
            }
        }
        
        return longest;
    }
};
最后来看下时间复杂度,存在一个循环,循环中有个操作都是需要常数时间,所以时间复杂度是O(n)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值