[LeetCode] Longest Valid Parentheses 最长有效括号
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
类似题目:
Different Ways to Add 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
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Longest Valid Parentheses 最长有效括号的更多相关文章
- [Leetcode] longest valid parentheses 最长的有效括号
Given a string containing just the characters'('and')', find the length of the longest valid (well-f ...
- [LeetCode] 32. Longest Valid Parentheses 最长有效括号
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
- [leetcode]32. Longest Valid Parentheses最长合法括号子串
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
- 032 Longest Valid Parentheses 最长有效括号
给一个只包含 '(' 和 ')' 的字符串,找出最长的有效(正确关闭)括号子串的长度.对于 "(()",最长有效括号子串为 "()" ,它的长度是 2.另一个例 ...
- 32. Longest Valid Parentheses最长有效括号
参考: 1. https://leetcode.com/problems/longest-valid-parentheses/solution/ 2. https://blog.csdn.net/ac ...
- [LeetCode] Longest Valid Parentheses 解题思路
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
- [LeetCode] Longest Valid Parentheses
第一种方法,用栈实现,最容易想到,也比较容易实现,每次碰到‘)’时update max_len,由于要保存之前的‘(’的index,所以space complexity 是O(n) // 使用栈,时间 ...
- [LeetCode] Longest Valid Parentheses 动态规划
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
- LeetCode: Longest Valid Parentheses 解题报告
Longest Valid Parentheses Given a string containing just the characters '(' and ')', find the length ...
随机推荐
- Mybatis框架 的快速入门
MyBatis 简介 什么是 MyBatis? MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除 了几乎所有的 JDBC 代码和参数的手工设置以及结果 ...
- 设置eclipse中自动添加get,set的注释为字段属性的注释
一:说明 首先具体来看一下是什么效果,上图可能会更清楚一点 就是在get/set中自动加上属性的注释,那我们要怎么配置呢? 二:配置 2.1:下载附件 下载附件 2.2:替换class 原生的ecli ...
- CSS知识总结(三)
CSS的常用样式 1.字体样式 1)字体名称(font-family) font-family : <family-name> 设置文字名称,可以使用多个名称,或者使用逗号分隔,浏览器 ...
- 安装完成后在命令行运行bash时报错0x80070057
在命令运行bash 提示如下: 解决方法,不启用旧版本控制台: 右键命令提示栏 打开属性,把勾选去掉如下图红色边框标识: 然后重启,就可以使用,也包括可以打开Bash on Unbuntu on Wi ...
- dicom网络通讯入门(1)
看标准 越看越糊,根本原因:dicom抽象得非常严重,是“专家”弄的.没办法. 又是什么服务类 又是什么sop,相信你把dicom标准看到头大 都不知如何下手. 不就是 socket么 这有何难. 首 ...
- js正则表达式校验非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- git push不用重复输入用户名和密码(解决方案)
每次git push都要输入用户名和密码,有点麻烦,就上网搜了下解决方案. 网上的解决方案有的讲得不清晰,逐个试了后,总结下两种有效的解决方案. 方案一: 1.在计算机安装盘(即一般为C盘)下找到 ...
- vs2013\2015UML系列之-类图
1.UML简介Unified Modeling Language (UML)又称统一建模语言或标准建模语言. 简单说就是以图形方式表现模型,根据不同模型进行分类,在UML 2.0中有13种图,以下是他 ...
- 【原】tomcat 7 启动报错:java.lang.NoSuchMethodError: javax.servlet.ServletContext.getSessionCookieConfig()Ljavax/servlet/SessionCookieConfig的解决
现象: tomcat 7 启动报错:java.lang.NoSuchMethodError: javax.servlet.ServletContext.getSessionCookieConfig() ...
- arcgis 许可异常的解决
异常现象: arcgis 许可服务管理器中无法重新读取许可,许可服务启动后立即停止. 解决方法: 1.卸载license:安装新的license!重新破解,替换license文件夹BI ...