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] Longest Valid Parentheses 最长有效括号的更多相关文章

  1. [Leetcode] longest valid parentheses 最长的有效括号

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

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

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

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

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

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

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

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

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

  6. [LeetCode] Longest Valid Parentheses 解题思路

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

  7. [LeetCode] Longest Valid Parentheses

    第一种方法,用栈实现,最容易想到,也比较容易实现,每次碰到‘)’时update max_len,由于要保存之前的‘(’的index,所以space complexity 是O(n) // 使用栈,时间 ...

  8. [LeetCode] Longest Valid Parentheses 动态规划

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

  9. LeetCode: Longest Valid Parentheses 解题报告

    Longest Valid Parentheses Given a string containing just the characters '(' and ')', find the length ...

随机推荐

  1. JavaScript结构三层——思想快速介绍

    本文版权归博客园和作者吴双本人所有,转载和爬虫请注明原文地址 http://www.cnblogs.com/tdws/,我是博客园蜗牛,我们共同进步. 今天讨论的是什么 如果你的工作中需要写JavaS ...

  2. springboot 学习资源推荐

    springboot 是什么?对于构建生产就绪的Spring应用程序有一个看法. Spring Boot优先于配置的惯例,旨在让您尽快启动和运行.(这是springboot的官方介绍) 我们为什么要学 ...

  3. 多线程中的volatile和伪共享

      伪共享 false sharing,顾名思义,“伪共享”就是“其实不是共享”.那什么是“共享”?多CPU同时访问同一块内存区域就是“共享”,就会产生冲突,需要控制协议来协调访问.会引起“共享”的最 ...

  4. 如何在Windows Server 2008 R2 SP1安装Redis-x64-3.2.100,并且自动注册服务

    1.官网:http://redis.io/ 2.下载地址:https://github.com/MSOpenTech/redis/releases 3.最新的安装包: 4.点击msi文件开始安装. 5 ...

  5. jdk源码分析PriorityQueue

    一.结构 PriorityQueue是一个堆,任意节点都是以它为根节点的子树中的最小节点 堆的逻辑结构是完全二叉树状的,存储结构是用数组去存储的,随机访问性好.最小堆的根元素是最小的,最大堆的根元素是 ...

  6. linux使用wkhtmltopdf报错error while loading shared libraries:

    官网提示 linux需要这些动态库.depends on: zlib, fontconfig, freetype, X11 libs (libX11, libXext, libXrender) 在li ...

  7. SQL Server导入数据时“启用标示插入”详解

    在SQL Server中导入数据时,会有一个"启用标示插入"的选项,突然间懵逼了,这到底啥意思?我选与不选这个选项,结果好像没区别!不科学啊这,"存在即合理", ...

  8. opts=opts | |{}

    var opts=opts || {}这个语句是一个赋值或者初始化语句 该语句在opts已经被初始化过后opts的值不变,即执行var opts=opts这一部分. 当opts未被初始化,即typeo ...

  9. 窗体作为控件嵌入panel

    EyeView frm = new EyeView(); frm.TopLevel = false; frm.Parent = this.panel1; frm.FormBorderStyle = F ...

  10. string.empty , "" , null 以及性能的比较

    一:这种结论,个人觉得仍然存疑 http://www.cnblogs.com/wangshuai901/archive/2012/05/06/2485657.html 1.null    null 关 ...