您的位置:首页 > 其它

[LeetCode] Longest Valid Parentheses

2015-05-13 22:11 399 查看
题目两种解法:【转】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?





class Solution {
public:
int longestValidParentheses(string s) {
int len = s.length();
if(len<2)
return 0;
int max = 0;
int *dp = new int[len];
for(int k = 0;k<len;k++)//把辅助数组清空,存储为0
dp[k] = 0;
for(int i = len-2;i>=0;i--)
{
if(s[i] == '(')//只对左括号处理,右括号在数组中存储为0
{
int j = i+1+dp[i+1];//计算与当前左括号匹配的右括号的位置。可能存在也可能不存在
if(j<len && s[j] == ')')//确保位置不能越界
{
dp[i] = dp[i+1] + 2;//找到了相匹配的右括号,当前数组中存储的最长长度是它后一个位置加2,后一个位置可能存储长度是0
if(j+1<len)//这是连接两个子匹配的关键步骤
dp[i] += dp[j+1];//在j的后面可能已经存在连续的匹配,要记得加上。dp[j+1]存储了以j+1开始的匹配
}
if(dp[i]>max)
max = dp[i];//更新最长长度
}

}
return max;
}
};

一维简单动态规划,思想是:对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

#define pb push_back
#define vi vector<int>

int longestValidParentheses(string s)
{
int sz=s.length();
if ( sz<=1 ) return 0;

vector<char> SWithGuard(sz+2);
vector<char>& swg=SWithGuard;
//swg.reserve(sz+2);
swg[0]=swg[sz+1]='#';
copy(s.begin(),s.end(),&swg[1]);


vi idx(sz+2,-1);

int i,j;

for(i=sz+1;i>0;i--)
{
if (swg[i]=='(')
{
j=i+1;
while(swg[j]=='('&&idx[j]!=-1)
j=idx[j]+1;
if (swg[j]==')')
idx[i]=j;
}
}

int longest=0;
int cur=0;
for(i=1;i<sz+2;)
{
if (idx[i]==-1)
{
longest=max(longest,cur);
cur=0;
i++;
}
else
{
cur+=idx[i]-i+1;
i=idx[i]+1;
}
}
return longest;
}

这里描述了另一种有效的方法: 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 below
13         // DO NOT write int main() function
14         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             else
23             {
24                 Node node = st.top();
25                 if (node.c == '(')
26                 {
27                     st.pop();
28                     ret = max(ret, i - st.top().index);
29                 }
30                 else
31                     st.push(Node(c, i));                   
32             }
33         }
34         
35         return ret;
36     }
37 };
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: