LeetCode 32. 最长有效括号
32. 最长有效括号
给你一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号 子串 的长度。
左右括号匹配,即每个左括号都有对应的右括号将其闭合的字符串是格式正确的,比如 “(()())”。
示例 1:
输入:s = “(()”
输出:2
解释:最长有效括号子串是 “()”
示例 2:
输入:s = “)()())”
输出:4
解释:最长有效括号子串是 “()()”
示例 3:
输入:s = “”
输出:0
提示:
0 <= s.length <= 3 * 104
s[i] 为 ‘(’ 或 ‘)’
题解
题目很好看懂,找到最长有效括号
由于每一处的最长有效括号仅仅取决于前面的选择,与后面无关,及无后效性
自然想到使用动态规划进行解题
注意到最长有效括号是连续的
所以我们定义 dp[ i ] 表示以下标 i 为结尾的字符串的最长有效括号
对于任意位置的 dp[ i ]
如果 s[ i ] 是 ‘(’,显然以其为结尾不可能是有效括号,dp[ i ]=0
如果 s[ i ] 是 ‘)’,就需要与前面的 ‘(’,进行匹配
匹配的情况有
- 直接和 s[ i-1 ] 匹配
- 和更前面的匹配,同时包裹住有效的括号,如"(()())"
如果 s[ i-1 ] 是 “(”,满足第一种情况,dp[ i ]=dp[ i-2 ]+2
如果 s[ i-1 ] 是 “)”,需要去更前面寻找匹配的括号
但是因为同时需要包裹住有效括号,形成连续的括号,dp[ i-1 ] 必须大于0,否则 dp[ i ]=0
若dp[ i-1 ] 大于0,还是根据连续性,我们要去找的括号一定是紧挨着 s[ i-1 ] 形成的有效括号的左侧的第一个符号
及下标 i-1 减去有效括号的个数,s[ i-1-dp[ i-1 ] ]
如果 s[ i-1-dp[ i-1 ] ] 不是 ‘(’,这个位置就无法形成有效括号,dp[ i ]=0
如果是’(',我们还需要考虑这个符号左边(及s[ i-1-dp[ i-1 ]-1 ])是否有连续括号,有的话还能一起连上
所以括号总长度是自己及包裹的长度和左边的括号长度之和
dp[ i ]=i - (i-1-dp[ i-1 ]) + 1 + dp[ i-1-dp[ i-1 ]-1 ]
这样遍历完字符串,我们知道了以所有字符为结尾的最长有效括号,取其中最大值便是答案
计算过程中涉及到类似 dp[ i-1-dp[ i-1 ]-1 ] 记得注意越界问题
代码如下↓
class Solution {
public:int longestValidParentheses(string s) {int n=s.size();vector<int> dp(n,0);int res=0;for(int i=1;i<n;i++){if(s[i]=='('){dp[i]=0;}else{if(s[i-1]=='('){if(i==1){dp[i]=2;}else{dp[i]=dp[i-2]+2;}}else{if(dp[i-1]==0){dp[i]=0;}else{if(i-1-dp[i-1]>-1 && s[i-1-dp[i-1]]=='('){dp[i]=i-(i-1-dp[i-1])+1;if(i-1-dp[i-1]-1>-1){dp[i]+=dp[i-1-dp[i-1]-1];}}else{dp[i]=0;}}}}if(dp[i]>res){res=dp[i];}}return res;}
};