题目描述
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例
示例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/