LeetCodeHot_32——《最长有效括号》
解题思路:这道题一看就是动态规划的解题的方法了,按照动态规划五部曲来做的话:
①确定dp数组(dp table)以及下标的含义:
dp[i] → 第i个元素表示下标为i的字符结尾的最长有效子字符串的长度。
②确定递推公式:
看第 i 个元素:
1° s[i] = ' ( ' 第 i 个元素为左括号的时候,这个元素没办法和之前的任意一个元素组成有效括 号对的,所以此时dp[i]=0。
2° s[i] = ' ) ' 第 i 个元素为右括号的时候,此时就需要看s[i-1]了,这个前一个位置的括号也是有两种情况的:
1)s[i-1]=' ( ' ,第i个元素前一个元素是左括号,这样的话第 i-1 个元素和第 i 个元素是可以组成有效括号对的,所以这时就可以在所求长度上 +2 。所以此时 dp[i] = dp[i-2]+2;
2)s[i-1]=' ) ',第i个元素前一个元素是右括号,这样第 i-1 和第 i 个元素是无法组成有效括号对的,但是此时s[i-1]和s[i]的组成形式是" ) ) ",所以如果s[i]能组成有效括号对的前提就是s[i-1]已经和别人组成过了,否则,s[i-1]是在s[i]前边的,组成也是s[i-1]先组成。所以我们只需要找到和s[i]配对的括号对的位置:i-dp[i-1]-1(这里的理解其实就是,先看dp[i-1],代表的是下标为 i-1 的字符的括号对的长度,i-dp[i-1] 的意思就是和 i-1 位置的括号匹配的那个左括号,i-dp[i-1]-1 就是和这个右括号的匹配的左括号了)。
如果:此时的s[i-dp[i-1]-1] = ' ( ',那么总长度就要加2,结果就是dp[i] = dp[i-1]+2,但是这里实际上的意思是s[i]与s[i-1]都各自有一对括号对——" ( ( ) ) ",所以还要加上之前的长度,也就是dp[i] = dp[i-1]+dp[ i-dp[i-1]-2 ]+2
所以:递推公式就可以确定了:
③dp数组如何初始化:
初始化dp[i] = 0;
dp[0]=0,dp[1]=0;
④确定遍历顺序
所以这里遍历只需要遍历字符串 s 就可以了、
⑤举例推导dp数组
具体代码:
int longestValidParentheses(string s) {
int size = s.length();
vector<int> dp(size, 0);//定义一个含有size个元素的数组,每个值都是0;
int maxNum = 0;//定义最后返回的长度最大值
for (int i = 1; i < size; i++)
{
if (s[i] == ')')
{
if (s[i - 1] == '(')
{
dp[i] = 2;
if (i - 2 >= 0)
{
dp[i] = dp[i] + dp[i - 2];
}
}
else if (dp[i - 1] > 0)
{
if ((i - dp[i - 1] - 1) >= 0 && s[i - dp[i - 1] - 1] == '(')
{
dp[i] = dp[i - 1] + 2;
if ((i - dp[i - 1] - 2) >= 0)
{
dp[i] = dp[i] + dp[i - dp[i - 1] - 2];
}
}
}
}
maxNum = max(maxNum, dp[i]);
}
return maxNum;
}