题目
给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
示例 :
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
思路一:暴力计算
合法括号是成对出现的,所以就判断[字符串长度/2个字符]是否是合法括号,如果是,那么就是最大长度了,举例:加入一个字符串长度是12,那么最大的合法括号就是6对,按照题目计算6*2=12,最大长度是12,我们的思路就是先从最大长度来判断,是否存在这样的可能,存在那题目直接就找到正确答案了,如果12的长度没找到,在找长度为10的,依次8,6,4,2,如果2也没找到,那就连一对合法括号都没有,return 0。
/**
* 暴力解法
* 合法括号是成对出现的,所以就判断 字符串长度/2个字符是否是合法括号
* 是就是最大长度了
* @param s
* @return
*/
public static int longestValidParentheses(String s) {
int result = 0;
Character le = new Character('(');
Character ri = new Character(')');
int m =s.length()%2;
int n = s.length()-m;
for(; n>=2; n=n-2) {
for(int i=0; i+n<=s.length(); i++) {
Stack<Character> stack = new Stack<>();
for(int j=i; j<i+n; j++) {
if(le.equals(s.charAt(j))) {
stack.push(s.charAt(j));
}
if(ri.equals(s.charAt(j))) {
if(stack.empty()) {
result = -1;
break;
}
Character peek = stack.peek();
if(!le.equals(peek)) {
continue;
} else {
stack.pop();
}
}
}
if(stack.isEmpty()) {
if(result <0) {
result = 0;
continue;
}
return n;
}
}
}
return 0;
}
按照上面的思路和代码,是没有问题的,但是这样解效率太低,leetcode还是不通过,因为超时,所以我们就要换一个思路,这个思路也比较容易理解。
思路二就是用stack来解题
/**
* 识别成对括号
* 检查stack是否为空
* 检查中间括号是否把合法括号分割开,计数要重新开始
* @param s
* @return
*/
public static int longestValidParentheses(String s) {
int max_len = 0;
Character le = new Character('(');
Character ri = new Character(')');
Stack<Integer> stack = new Stack<>();
stack.push(-1);
for(int i=0; i<s.length(); i++) {
if(le.equals(s.charAt(i))) {
stack.push(i);
continue;
}
stack.pop();
if(ri.equals(s.charAt(i))) {
if(stack.isEmpty()) {
stack.push(i);
continue;
}
max_len = Math.max(i-stack.peek(), max_len);
}
}
return max_len;
}
这里有一些巧妙的地方,其一就是先往stack中放一个-1,其二就是当stack出栈变为空了之后,就将一个右括号的下标入栈,为什么这样做呢,其实就是为了计算连续有效括号的长度。细品一下。
还有一种思路是采用动态规划,这里主要以思路简单易于理解,易于入门为主,dp就先不在这里讲解了。