1. 问题:给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
示例1
输入:"(()" 输出:2
解释:最长有效括号子串为:"()"
示例2
输入:"()(()" 输出:2
解释:最长有效括号子串为:"()"
示例3
输入:"()(())" 输出:6
解释:最长有效括号子串为:"()(())"
示例4
输入:")()())" 输出:4
解释:最长有效括号子串为:"()()"
2. 问题分析:
方法1:利用栈的思想,记录索引,对索引进行处理来得到最长有效括号子串数目。
举例:s="())))((())" 设 i 为s的索引, 数组stack[-1,...],长度为(s.length+1),top为stack的索引(类似于栈顶索引,刚开始学java,栈不会使用,用数组代替),初始化时top=0。遍历s如下图所示:
算法分为两步走:
a:如果 s[i] == "(" ,top++,把 i 存储到stack[top]数组中
b:如果 s[i] == ")",top--,然后对top进行条件判断:
如果top<0,top++,stack[top]=i
否则,Max_len = max( Max_len, i-stack[top] )
方法2: 使用动态规划的思想
设dp[i]等于 s 中长度为 i 的字符串的最长的有效括号数量,
如s="()(())",dp=[0 2 0 0 2 6 ]。
观察到一个现象:s[0]与s[1]配对,s[3]与s[4]配对,s[2]与s[5]配对,(待续。。。)
3. 方法1 java程序:
class Solution {
public int longestValidParentheses(String s) {
//String s ="()))))(())";
int top = 0; // stack[]的索引 相当于栈顶索引
int [] stack = new int [s.length()+1]; // 申请一个和(s+1)一样大的数组
stack[0] = -1; // 第一个值赋值为-1
int max_len = 0; // 存储最长有效字括号
int leth =0; // 中间变量
// 遍历s中的每一个元素
for (int i=0;i<s.length();i++){
// 如果s[i]中的元素为"(",将位置 i 存入stack中
if (s.charAt(i) == '('){
stack[++top] = i;
}
//否则,
else{
// top索引减1
top--;
// top<0时,top++,并存储坐标i
if (top<0){
stack[++top] = i;
}
// top >= 0时,s当前位置i减去top指向的stack中的值
else{
leth = i - stack[top];
// 和上次最大值进行比较,最大值赋给max_len
if (max_len<leth){
max_len = leth;
}
}
}
}
System.out.println("最长有效括号为:"+max_len);
}
}
4. 方法2 java程序:
public static int longestValidParentheses(String s) {
if (s == null || s.length() == 0)
return 0;
int result = 0;
int[] dp = new int[s.length()];
for (int i = 0; i < s.length(); i++) {
if (i == 0)
continue;
if (s.charAt(i) == ')') {
if (s.charAt(i - 1) == '(') {
dp[i] = 2 + ( i - 2 >= 0 ? dp[i - 2] : 0 );
} else if (i - dp[i - 1] - 1 >= 0 && s.charAt(i - dp[i - 1] - 1) == '(') {
dp[i] = dp[i - 1] + 2 + (i - dp[i - 1] - 2 >= 0 ? dp[i - dp[i - 1] - 2] : 0);
}
result = result>dp[i] ? result:dp[i]; // result = Integer.max(result, dp[i]);
}
}
return result;
}