[LeetCode] Longest Valid Parentheses

来源:互联网 发布:淘宝客优惠券推广 编辑:程序博客网 时间:2024/06/06 03:53

题目两种解法:【转】http://blog.csdn.net/yapian8/article/details/28239003

求最长合法匹配的长度,这道题可以用一维动态规划逆向求解。假设输入括号表达式为String s,维护一个长度为s.length的一维数组dp[],数组元素初始化为0。 dp[i]表示从s[i]到s[s.length - 1]包含s[i]的最长的有效匹配括号子串长度。则存在如下关系:

  • dp[s.length - 1] = 0;
  • i从n - 2 -> 0逆向求dp[],并记录其最大值。若s[i] == '(',则在s中从i开始到s.length - 1计算dp[i]的值。这个计算分为两步,通过dp[i + 1]进行的(注意dp[i + 1]已经在上一步求解):
    • 在s中寻找从i + 1开始的有效括号匹配子串长度,即dp[i + 1],跳过这段有效的括号子串,查看下一个字符,其下标为j = i + 1 + dp[i + 1]。若j没有越界,并且s[j] == ‘)’,则s[i ... j]为有效括号匹配,dp[i] =dp[i + 1] + 2。
    • 在求得了s[i ... j]的有效匹配长度之后,若j + 1没有越界,则dp[i]的值还要加上从j + 1开始的最长有效匹配,即dp[j + 1]。

 

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. class Solution {  
  2. public:  
  3.     int longestValidParentheses(string s) {  
  4.         int len = s.length();  
  5.         if(len<2)  
  6.           return 0;  
  7.         int max = 0;  
  8.         int *dp = new int[len];  
  9.         for(int k = 0;k<len;k++)//把辅助数组清空,存储为0  
  10.          dp[k] = 0;  
  11.         for(int i = len-2;i>=0;i--)  
  12.         {  
  13.           if(s[i] == '(')//只对左括号处理,右括号在数组中存储为0  
  14.           {  
  15.             int j = i+1+dp[i+1];//计算与当前左括号匹配的右括号的位置。可能存在也可能不存在  
  16.             if(j<len && s[j] == ')')//确保位置不能越界  
  17.             {  
  18.               dp[i] = dp[i+1] + 2;//找到了相匹配的右括号,当前数组中存储的最长长度是它后一个位置加2,后一个位置可能存储长度是0  
  19.               if(j+1<len)//这是连接两个子匹配的关键步骤  
  20.                 dp[i] += dp[j+1];//在j的后面可能已经存在连续的匹配,要记得加上。dp[j+1]存储了以j+1开始的匹配  
  21.             }  
  22.             if(dp[i]>max)  
  23.               max = dp[i];//更新最长长度  
  24.           }  
  25.             
  26.         }  
  27.         return max;  
  28.     }  
  29. }; 

一维简单动态规划,思想是:对S中从后向前的每个 ' ( ' ,我们来计算它最远对应到的那个‘)’的位置,在这两个字符中间的字符能够组成一个合法的括号串。

记当前 '(' 的下标为 i ,用idx[] 来保存每个i的最右合法匹配位置:

1. 如果它的右边是 ' ) ',那明显最远的合法匹配位置就到这个‘)’为止,idx[i] = i+1;

2.如果它的右边是 ' ( ',因为我们已经计算过它的最右合法匹配位置,在接着这个最右位置继续向右找 ;

3.如果右边不是 ‘( )’,则没有合法的匹配位置, idx = -1 ;

 

例子: 比如  s = " ( ) ( ( ( ) ) "

序号     0    1     2   3   4   5   6   7

             (      )     (    (    (    (     )    )

 

现在来计算idx的值;

1.从右向左找到第一个 ‘ ( ’,序号为5,右边是 ‘)’,匹配,所以 idx[ 5 ] = 6;

2.第二个s[4] ,右边是'(' ,它的匹配是6,所以跳到6再看右边,是‘)’,匹配,所以 idx[ 4 ] = 7;

3. 第三个s[3],右边是 '( " ,它的匹配是7,跳到7再看右边,越界,没有匹配,所以idx[3] = -1;

4.第四个s[2] ,右边是‘(’,但右边的‘(‘的idx为-1,即没有合法的匹配,所以s[2]自然也不能向右有合法匹配,idx[2]=-1;

5. s[0]  = 1;

 

所以得到 idx 数组  :

序号     0    1     2   3   4   5   6   7

             (      )     (    (    (    (     )    )

idx        1    -1    -1 -1  7   6  -1   -1

 

现在可以计算最长合法长度了,计算很简单,见代码。

另外为了防止去判断越界,在原S两端添加了哨兵字符;

[cpp] view plaincopy
  1. #define pb push_back  
  2. #define vi vector<int>  
  3.   
  4. int longestValidParentheses(string s)  
  5. {  
  6.     int sz=s.length();  
  7.     if ( sz<=1 ) return 0;  
  8.   
  9.     vector<char> SWithGuard(sz+2);  
  10.     vector<char>& swg=SWithGuard;  
  11.     //swg.reserve(sz+2);  
  12.     swg[0]=swg[sz+1]='#';  
  13.     copy(s.begin(),s.end(),&swg[1]);  
  14.       
  15.   
  16.     vi idx(sz+2,-1);  
  17.   
  18.     int i,j;  
  19.   
  20.     for(i=sz+1;i>0;i--)  
  21.     {  
  22.         if (swg[i]=='(')  
  23.         {  
  24.             j=i+1;  
  25.             while(swg[j]=='('&&idx[j]!=-1)  
  26.                 j=idx[j]+1;  
  27.             if (swg[j]==')')  
  28.                 idx[i]=j;  
  29.         }  
  30.     }  
  31.   
  32.     int longest=0;  
  33.     int cur=0;  
  34.     for(i=1;i<sz+2;)  
  35.     {  
  36.         if (idx[i]==-1)  
  37.         {  
  38.             longest=max(longest,cur);  
  39.             cur=0;  
  40.             i++;  
  41.         }  
  42.         else  
  43.         {  
  44.             cur+=idx[i]-i+1;  
  45.             i=idx[i]+1;  
  46.         }  
  47.     }  
  48.     return longest;  
  49. }  



这里描述了另一种有效的方法: http://www.cnblogs.com/remlostime/archive/2012/11/25/2787878.html

 

转载自:【】http://www.cnblogs.com/remlostime/archive/2012/11/25/2787878.html

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

For "(()", the longest valid parentheses substring is "()", which has length = 2.

Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

复制代码
 1 struct Node 2 { 3     char c; 4     int index; 5     Node(){} 6     Node(char _c, int idx):c(_c), index(idx){} 7 }; 8  9 class Solution {10 public:11     int longestValidParentheses(string s) {12         // Start typing your C/C++ solution below13         // DO NOT write int main() function14         stack<Node> st;15         st.push(Node(')', -1));16         int ret = 0;17         for(int i = 0; i < s.size(); i++)18         {19             char c = s[i];20             if (c == '(')21                 st.push(Node(c, i));22             else23             {24                 Node node = st.top();25                 if (node.c == '(')26                 {27                     st.pop();28                     ret = max(ret, i - st.top().index);29                 }30                 else31                     st.push(Node(c, i));                   32             }33         }34         35         return ret;36     }37 };
0 0
原创粉丝点击