LEETCODE算法注解32:
给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。
示例 1:
输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”
示例 2:
输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”
提供三种解法:
1>暴力解决
找到给定字符串中所有的有效子串,找出最长的。那又如何找出所有字串呢?
public class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
stack.push('(');//左括号进栈
} else if (!stack.empty() && stack.peek() == '(') {
stack.pop();//遇到右括号,栈顶为左括号,出栈
} else {
return false;
}
}
return stack.empty();
}
public int longestValidParentheses(String s) {
int maxlen = 0;
//双重循环来截出字串,判断字串有效则比较长度,无效跳过
for (int i = 0; i < s.length(); i++) {
for (int j = i + 2; j <= s.length(); j+=2) {
if (isValid(s.substring(i, j))) {
maxlen = Math.max(maxlen, j - i);
}
}
}
return maxlen;
}
}
2>不再是一段段截取子串来判断,而是在一次遍历整个字符串的过程中找出有最长效子串。
上图最长子串为4,可以看作是4-0=4
用最后一个字符对应的数字4减去有效子串的第一个字符的前一个字符对应的数字下标0.
第一个字符前是没有字符的,该如何处理呢?我们都知道此题最终都是要入栈处理的,因此,我们将-1作为第一个值直接入栈,就可以解决此问题。因此变为3-(-1)=4。
对于遇到的每个 ‘(’ ,我们将它的下标放入栈中。
对于遇到的每个 ‘)’ ,我们弹出栈顶的元素并将当前元素的下标与新栈顶元素下标作差,得出当前有效括号字符串的长度。通过这种方法,我们继续计算有效子字符串的长度,并最终返回最长有效子字符串的长度。
又因为弹出当前栈顶元素后,栈可能为空。
重点:栈为空时是不可能配对成功的。
如:))
-1进栈,-1出栈,0进栈,0出栈,1进栈,可见栈内始终只有一个数据
())()
-1进栈,0进栈,0出栈,-1出栈(此时栈空),2进栈,3进栈,3出栈
说明:当栈空时,都是因为没有配对成功。因此让当前“)”的下标入栈,充当下一个可能成功匹配子串的前一个字符,用于计算。
public class Solution {
public int longestValidParentheses(String s) {
int maxans = 0;
Stack<Integer> stack = new Stack<>();
stack.push(-1);
for (int i = 0; i < s.length(); i++) {//遍历整个串
{ //碰到左边字符,此字符对应的数字进栈
if (s.charAt(i) == '(')
stack.push(i);
} else {
stack.pop();//弹出栈顶字符
if (stack.empty()) {//栈为空,元素入栈
stack.push(i);
} else {//不为空,计算子串长度
maxans = Math.max(maxans, i - stack.peek());
}
}
}
return maxans;
}
}