leetcode32.最长有效括号

题目描述

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

示例

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

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

题解

法1 暴力破解法(参考官方解答)

原理: 由于有效括号子串长度必为偶数,所以从小于等于原字符串长度的最大偶数开始取值,采用的方法,检验以该数为长度的子串是否存在有效的,若存在返回该长度;
否则依次减2,再进行检验,直至检验出最大的有效子串长度,并返回该长度
暴力破解法在某些场合下还是挺有用的!!!!
图例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

法2 动态规划法(参考官方解答)
重要!!!

使用动态规划方法的过程中需要明确
1.需要记录的状态是什么
2.如何从这个状态转移到下个状态,也就是如何求解状态转移方程

思路: 定义 dp[i]表示以下标 i 字符结尾的最长有效括号的长度。首先将dp数组全部初始化为 0。可以推断以‘(’结尾的子串一定不是有效子串,对应的dp[i]为0。

从前往后遍历字符串求解dp 值,每两个字符检查一次:
1. s[i]=‘)’ 且s[i−1]=‘(’,也就是字符串形如 “……()”,我们可以推出:
dp[i]=dp[i−2]+2
2. s[i]=‘)’ 且 s[i−1]=‘)’,也就是字符串形如 “……))”,我们可以推出:
如果s[i−dp[i−1]−1]=‘(’,那么
dp[i]=dp[i−1]+dp[i−dp[i−1]−2]+2
否则 dp[i]=0

最后的答案即为 \textit{dp}dp 数组中的最大值。

代码

class Solution {
public:
    int longestValidParentheses(string s) {
        int len = s.size();
        //给dp赋上长度为len,值为0的初值
        vector<int> dp(len);
        //for_each(dp.begin(), dp.end(), print());
        //第0个字符的有效字符长度肯定为0
        if (len == 1 || len == 0) return 0;
        if (s[1] == ')' && s[0] == '(') dp[1] = 2;
        for (int i = 2; i < len; i++) {
            if (s[i] == ')') {
                //s[i] = ‘)’且 s[i - 1] =‘(’的情况
                if (s[i - 1] == '(') dp[i] = dp[i - 2] + 2;
                //s[i] = s[i - 1] =‘)’的情况
                //此处判断i - dp[i - 1] - 1 >= 0是为了考虑退化情况
                else if (i - dp[i - 1] - 1 >= 0 && s[i - dp[i - 1] - 1] == '(') {
                    //此处判断i - dp[i - 1] - 2 < 0是为了考虑退化情况
                    if (i - dp[i - 1] - 2 < 0) dp[i] = dp[i - 1] + 2;
                    else dp[i] = dp[i - dp[i - 1] - 2] + dp[i - 1] + 2;
                }
                else dp[i] = 0;
            }
        }

        int maxLen = 0;
        for (int j = 0; j < len; j++) {
            if (dp[j] > maxLen) maxLen = dp[j];
        }

        return maxLen;
    }
};

参考链接

https://leetcode-cn.com/problems/longest-valid-parentheses/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值