Leetcode 32.最长有效括号

最长有效括号

问题描述

给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: "(()" 输出: 2 解释: 最长有效括号子串为 "()" 示例 2:

输入: ")()())" 输出: 4 解释: 最长有效括号子串为 "()()"

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-valid-parentheses

思路

1、栈:

栈中保存的是字符串字符下标.

https://leetcode.com/problems/longest-valid-parentheses/discuss/14126/My-O(n)-solution-using-a-stack

  1. 从头到尾扫描栈,如果是“(”则压入栈。

  2. 如果是")",判断栈顶元素。如果栈顶元素是"(",则可以匹配,弹出栈顶。如果是“)”,则不能匹配,前一个非法,当前也非法,把当前下标入栈。

  3. 最后留在栈内的都是不能匹配的括号的下标。如果最后栈空,说明所有括号相互匹配,直接返回n。

  4. 可以匹配的字符串就在栈中这些下标中间,找到不匹配括号下标之间间隔的最大值即为最长有效括号(考虑最长括号从头开始情况)。

改进:动态计算最大长度。

栈顶表示最后无效括号的下标,当遇到"("时压栈,遇到")"时总是弹出栈,因为只有最后一个无效括号的下标有记录的必要,前面如果时左括号本来就应该弹,是右括号也没有保存下标的必要。如果从头开始的括号序列是最长,那么有先压入栈的-1计算。如果遇到栈空,说明-1已经被弹了(而不是左括号被弹),当前右括号必为多余的。

代码:

class Solution {
   public int longestValidParentheses(String s) {
       char[] arr = s.toCharArray();
       Stack<Integer> stack=new Stack<>();
       stack.push(-1);
       int maxLen=0;
       for (int i=0;i<arr.length;i++){
           if (arr[i]=='('){
               //栈中保存下标
               //栈顶保存了最后一个无效括号的位置
               stack.push(i);
          }
           else {
               stack.pop();
               if(stack.isEmpty()){//如果为空,说明-1已经被弹,比非法,压入栈
                   stack.push(i);
              }
               else {//每个非法右括号都被先弹了,非空要么是左括号,要么是-1,故可以更新最长值
                   maxLen=Math.max(maxLen,i-stack.peek());
              }
          }
      }
       return maxLen;
  }
}

2、动态规划

dp表示以位置i(从1开始)结尾的括号之前最长的有效括号长度。

https://leetcode.com/problems/longest-valid-parentheses/discuss/14133/My-DP-O(n)-solution-without-using-stack

public int longestValidParentheses(String s) {
       //所有表示位置的变量默认从1开始
       int len=s.length();
       if(len<2){
           return 0;
      }
       int res=0;
       //dp表示以位置i(从1开始)结尾的括号之前最长的有效括号长度
       //dp[0],dp[1]必为0
       int dp[]=new int[len+1];
       char arr[]=s.toCharArray();
       for (int i = 2; i <= len; i++) {
           if(arr[i-1]=='('){
               dp[i]=0;
          }
           else {
               if(arr[i-2]=='('){
                   dp[i]=dp[i-2]+2;
              }
               else {
                   if(i-dp[i-1]-2>=0&&arr[i-dp[i-1]-2]=='('){
                       dp[i]=dp[i-dp[i-1]-2]+dp[i-1]+2;
                  }
                   else {
                       dp[i]=0;
                  }
              }
          }
           res=Math.max(res,dp[i]);
      }
       return res;
  }
posted @ 2019-08-14 21:54  pibaba  阅读(295)  评论(0编辑  收藏  举报