给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
一看这个题目,最值,典型的dp, 这题真的是花了我一个多小时,刷题都快刷哭了,昨天刚刚建立起来的觉得自己dp可的自信心又被摧毁的体无完肤,哎,还是要记录一下自己的解题历程。
对一道dp问题的求解可以分为四步:
- 确定状态: ---研究最优策略的最后一步 ---化为子问题
- 转移方程:根据子问题定义直接得到
- 初始条件和边界情况
- 计算顺序:利用之前的计算结果
解题思路:
首先我们定义一个dp数组,其中第 i个元素表示以下标为 i 的字符结尾的最长有效子字符串的长度。
对于最优的策略,一定有最后一个元素 s[i].
所以,我们先看第 i 个位置,这个位置的元素 s[i]可能有如下两种情况:
1 s[i]=='(' 此时s[i]=0
2 s[i]==')' 在这种情况下还有两种情况
如图:
若s[i-1]=='(' 则dp[i]=dp[i-1]+2 要保证i-1>=0
若s[i-1]==')' 则dp[i]=dp[i-1]+2+[i-dp[i-1]-2] 同样要保证i-dp[i-1]-2>=0 且s[i-dp[i-1]-1]=='('
所以状态转移方程和边界条件就如上面所给出的,代码如下:
class Solution {
public int longestValidParentheses(String s) {
if(s==null||s.length()==0){
return 0;
}
char[] chs=s.toCharArray();
int len=chs.length;
int[] df=new int[len];
int res=0;
for(int i=1;i<len;i++){
//第一种情况
if(chs[i]==')'&&chs[i-1]=='('){
//注意边界情况
if(i-2>=0){
df[i]=df[i-2]+2;
}else{
df[i]=2;
}//以下是第二种情况
}else if(chs[i]==')'&&df[i-1]>0){
if(i-df[i-1]-1>=0&&chs[i-df[i-1]-1]=='('){
df[i]=2+df[i-1];
//注意边界情况
if(i-df[i-1]-2>0){
df[i]+=df[i-df[i-1]-2];
}
}
}
//在chs[i]=='('的时候,df[i]=0,因为int类型数组初始值就是0,所以就不用再做处理
res=Math.max(df[i],res);
}
return res;
}
}
刷题真的是个漫长而很懊恼的事情,愿大家都能早日跳出这个坑,共勉。