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

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

这道求最长有效括号比之前那道 Valid Parentheses 难度要大一些,这里还是借助栈来求解,需要定义个 start 变量来记录合法括号串的起始位置,遍历字符串,如果遇到左括号,则将当前下标压入栈,如果遇到右括号,如果当前栈为空,则将下一个坐标位置记录到 start,如果栈不为空,则将栈顶元素取出,此时若栈为空,则更新结果和 i - start + 1 中的较大值,否则更新结果和 i - st.top() 中的较大值,参见代码如下:

解法一:

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

还有一种利用动态规划 Dynamic Programming 的解法,可参见网友喜刷刷的博客。这里使用一个一维 dp 数组,其中 dp[i] 表示以 s[i-1] 结尾的最长有效括号长度(注意这里没有对应 s[i],是为了避免取 dp[i-1] 时越界从而让 dp 数组的长度加了1),s[i-1] 此时必须是有效括号的一部分,那么只要 dp[i] 为正数的话,说明 s[i-1] 一定是右括号,因为有效括号必须是闭合的。当括号有重合时,比如 "(())",会出现多个右括号相连,此时更新最外边的右括号的 dp[i] 时是需要前一个右括号的值 dp[i-1],因为假如 dp[i-1] 为正数,说明此位置往前 dp[i-1] 个字符组成的子串都是合法的子串,需要再看前面一个位置,假如是左括号,说明在 dp[i-1] 的基础上又增加了一个合法的括号,所以长度加上2。但此时还可能出现的情况是,前面的左括号前面还有合法括号,比如 "()(())",此时更新最后面的右括号的时候,知道第二个右括号的 dp 值是2,那么最后一个右括号的 dp 值不仅是第二个括号的 dp 值再加2,还可以连到第一个右括号的 dp 值,整个最长的有效括号长度是6。所以在更新当前右括号的 dp 值时,首先要计算出第一个右括号的位置,通过 i-3-dp[i-1] 来获得,由于这里定义的 dp[i] 对应的是字符 s[i-1],所以需要再加1,变成 j = i-2-dp[i-1],这样若当前字符 s[i-1] 是左括号,或者j小于0(说明没有对应的左括号),或者 s[j] 是右括号,此时将 dp[i] 重置为0,否则就用 dp[i-1] + 2 + dp[j] 来更新 dp[i]。这里由于进行了 padding,可能对应关系会比较晕,大家可以自行带个例子一步一步执行,应该是不难理解的,参见代码如下:

解法二:

class Solution {
public:
int longestValidParentheses(string s) {
int res = , n = s.size();
vector<int> dp(n + );
for (int i = ; i <= n; ++i) {
int j = i - - dp[i - ];
if (s[i - ] == '(' || j < || s[j] == ')') {
dp[i] = ;
} else {
dp[i] = dp[i - ] + + dp[j];
res = max(res, dp[i]);
}
}
return res;
}
};

此题还有一种不用额外空间的解法,使用了两个变量 left 和 right,分别用来记录到当前位置时左括号和右括号的出现次数,当遇到左括号时,left 自增1,右括号时 right 自增1。对于最长有效的括号的子串,一定是左括号等于右括号的情况,此时就可以更新结果 res 了,一旦右括号数量超过左括号数量了,说明当前位置不能组成合法括号子串,left 和 right 重置为0。但是对于这种情况 "(()" 时,在遍历结束时左右子括号数都不相等,此时没法更新结果 res,但其实正确答案是2,怎么处理这种情况呢?答案是再反向遍历一遍,采取类似的机制,稍有不同的是此时若 left 大于 right 了,则重置0,这样就可以 cover 所有的情况了,参见代码如下:

解法三:

class Solution {
public:
int longestValidParentheses(string s) {
int res = , left = , right = , n = s.size();
for (int i = ; i < n; ++i) {
(s[i] == '(') ? ++left : ++right;
if (left == right) res = max(res, * right);
else if (right > left) left = right = ;
}
left = right = ;
for (int i = n - ; i >= ; --i) {
(s[i] == '(') ? ++left : ++right;
if (left == right) res = max(res, * left);
else if (left > right) left = right = ;
}
return res;
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/32

类似题目:

Remove Invalid Parentheses

Different Ways to Add Parentheses

Generate Parentheses

Valid Parentheses

参考资料:

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

https://bangbingsyb.blogspot.com/2014/11/leetcode-longest-valid-parentheses.html

https://leetcode.com/problems/longest-valid-parentheses/discuss/14126/My-O(n)-solution-using-a-stack

https://leetcode.com/problems/longest-valid-parentheses/discuss/14133/My-DP-O(n)-solution-without-using-stack

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] 32. Longest Valid Parentheses 最长有效括号的更多相关文章

  1. [leetcode]32. Longest Valid Parentheses最长合法括号子串

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  2. 32. Longest Valid Parentheses最长有效括号

    参考: 1. https://leetcode.com/problems/longest-valid-parentheses/solution/ 2. https://blog.csdn.net/ac ...

  3. [LeetCode] Longest Valid Parentheses 最长有效括号

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  4. leetcode 32. Longest Valid Parentheses

    Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...

  5. Java [leetcode 32]Longest Valid Parentheses

    题目描述: Given a string containing just the characters '(' and ')', find the length of the longest vali ...

  6. LeetCode 32 Longest Valid Parentheses(最长合法的括号组合)

    题目链接: https://leetcode.com/problems/longest-valid-parentheses/?tab=Description   Problem :已知字符串s,求出其 ...

  7. 032 Longest Valid Parentheses 最长有效括号

    给一个只包含 '(' 和 ')' 的字符串,找出最长的有效(正确关闭)括号子串的长度.对于 "(()",最长有效括号子串为 "()" ,它的长度是 2.另一个例 ...

  8. [LeetCode] 32. Longest Valid Parentheses (hard)

    原题链接 题意: 寻找配对的(),并且返回最长可成功配对长度. 思路 配对的()必须是连续的,比如()((),最长长度为2:()(),最长长度为4. 解法一 dp: 利用dp记录以s[i]为终点时,最 ...

  9. [Leetcode][Python]32: Longest Valid Parentheses

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 32: Longest Valid Parentheseshttps://oj ...

随机推荐

  1. Redis 设计与实现,看 SDS(Simple Dynamic String) 感悟

    Redis 设计与实现,看 SDS(Simple Dynamic String) 感悟 今天在看 Redis 设计与实现这本书的时候,发现了里面系统定义的数据结构 SDS,中文名为 简单动态字符串.对 ...

  2. ECMAScript 6.0 简要学习

    由于在学习vue的时候有许多自己不懂的语法,于是简单的学习一下ES6. 1.ES简介 ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版. ...

  3. linux部署java命令

    启动: #!/bin/bash source /etc/profile log() { echo `date +[%Y-%m-%d" "%H:%M:%S]` $1 } log &q ...

  4. 使用SolrJ客户端管理SolrCloud(Solr集群)

    1.使用SolrJ客户端管理SolrCloud(Solr集群). package com.taotao.search.service; import java.io.IOException; impo ...

  5. Python - 函数 - 第十四天

    Python 函数 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也 ...

  6. Struts2框架简单介绍

    如需,了解Struts2详情,请点击,传送门 工作原理 在Struts2 框架中的处理大概分为以下步骤: 1.客户端初始化一个指向servlet容器(例如Tomcat)的请求. 2.这个请求经过一系列 ...

  7. Hystrix核心熔断器

    在深入研究熔断器之前,我们需要先看一下Hystrix的几个重要的默认配置,这几个配置在HystrixCommandProperties 中 //时间窗(ms) static final Integer ...

  8. IDEA创建父模块与子模块

    1.IDEA点击New Project 2.点击+: 3.在[project]包下新建一个模块Moudle,名叫(springcloud)//root模块 4.继续添加模块Initializr持续ne ...

  9. RV64I基础整数指令集

    RV64I是RV32I的超集,RV32I是RV64I的子集.RV64I包括RV32I的所有40条指令,另外增加了12条RV32I中没有的指令,还有三条移位指令(slli, srli,srai)也进行小 ...

  10. 3 测试使用和LogCat日志

    测试概念: 1.根据是否知道源代码分: 黑盒测试:功能测试 白盒测试:编写代码进行测试 2.测试力度划分: 方法测试: 单元测试: 集成测试: 系统测试: 3.暴力程度划分: 压力测试: 冒烟测试:压 ...