最长有效括号

给你一个只包含 ‘(‘ 和 ‘)’ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例

  1. 输入:s = "(()"
  2. 输出:2
  3. 解释:最长有效括号子串是 "()"

解题

方法一:栈

通过栈,可以在遍历给定字符串的过程中去判断到目前为止扫描的子串的有效性,同时能得到最长有效括号的长度。
始终保持栈底元素为当前已经遍历过的元素中「最后一个没有被匹配的右括号的下标」,这样的做法主要是考虑了边界条件的处理,栈里其他元素维护左括号的下标。
需要注意的是,如果一开始栈为空,第一个字符为左括号的时候我们会将其放入栈中,这样就不满足提及的「最后一个没有被匹配的右括号的下标」,为了保持统一,我们在一开始的时候往栈中放入一个值为-1的元素。

1.初始化最大长度,初始化栈,-1入栈。
2.遍历:
1.遇到左括号:下标入栈
2.遇到右括号:出栈(弹出栈顶元素)
如果栈为空,当前右括号下标入栈 「最后一个没有被匹配的右括号的下标」
如果栈不为空,更新 maxlen = 当前右括号的下标减去栈顶元素。「以该右括号为结尾的最长有效括号的长度」
3.返回最长有效括号长度

  1. class Solution {
  2. //最长有效括号 - 子串及其长度
  3. //栈底 维护最后一个没有被匹配的右括号的下标
  4. public int longestValidParentheses(String s) {
  5. int maxans = 0;
  6. Deque<Integer> stack = new LinkedList<Integer>();
  7. stack.push(-1);
  8. for (int i = 0; i < s.length(); i++) {
  9. if (s.charAt(i) == '(') {
  10. stack.push(i);
  11. } else {
  12. stack.pop();
  13. if (stack.isEmpty()) {
  14. stack.push(i);
  15. } else {
  16. maxans = Math.max(maxans, i - stack.peek());
  17. }
  18. }
  19. }
  20. return maxans;
  21. }
  22. }
  1. //版本二:记录下标,同时输出子串
  2. class Solution {
  3. //保持栈底元素为当前已经遍历过的元素中「最后一个没有被匹配的右括号的下标」
  4. public int longestValidParentheses(String s) {
  5. int maxlen = 0;
  6. int left = 0,right = 0;
  7. String sub;
  8. Deque<Integer> stack = new LinkedList<>();
  9. stack.push(-1);
  10. for(int i = 0; i<s.length(); i++){
  11. if(s.charAt(i) == '('){
  12. stack.push(i);
  13. }else{
  14. stack.pop();
  15. if(stack.isEmpty()){
  16. stack.push(i);
  17. }else{
  18. if(i - stack.peek() > maxlen){
  19. maxlen = Math.max(maxlen, i - stack.peek());
  20. left = stack.peek();
  21. right = i;
  22. }
  23. }
  24. }
  25. }
  26. if(right != 0){ //空字符串处理
  27. sub = s.substring(left+1,right+1);
  28. System.out.println(left+1); //最长子串的左下标
  29. System.out.println(right); //最长子串的右下标
  30. System.out.println(sub); //最长有效子串
  31. }
  32. return maxlen;
  33. }
  34. }

方法二:动态规划