leetcode题集——longest-valid-parentheses

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.

解法一、利用栈,时间复杂度为O(n),空间复杂度为O(n)

基本思想:从头开始遍历字符串,遇到左括号则做入栈,遇到右括号则出栈。一个右括号能消去一个左括号。

不同的是,为了能够计算括号对的长度,还需要记录括号的下标。

当弹出一个左括号后,根据当前坐标减去栈中上一个(也就是pop之后的top元素)的坐标,可得到该有效括号对的长度。

//新建结构体,保存字符及下标
struct Node
{ char c;
  int index;
  Node() {}
  Node(char sc,int i)
  {
    this->c=sc;
	this->index=i;
  }
};

class Solution
{
public:
  int max(int a,int b)
  {
    return a>b?a:b;
  }
  int longestValidParentheses(string s)
  {
	stack<Node> sta;
	int ret=0;
	for(int i=0;i<s.size();i++)
	{
	  char sc=s[i];
	  if(sc=='(')//遇到左括号,则入栈
	    sta.push(Node(sc,i));
	  else
	  {
	    if(!sta.empty()&&sta.top().c=='(')
		{//当栈不为空,并且栈顶元素为左括号时
		  int curlen;
		  sta.pop();//出栈
		  if(sta.empty())
		  { 
		    curlen=i+1;//当出栈后,栈为空。说明已遍历过的字符串完全匹配
		  }
		  else
		  {
		    curlen=i-sta.top().index;//当前下标减去栈顶元素对应下标
		  }
		   ret=max(ret,curlen);//更新匹配子串的最大值
		}
		else//当遇到右括号,栈为空或者栈顶同为右括号,则入栈
		    sta.push(Node(sc,i));
	  }
	 
	}
	return ret;
  }
  
};

解法二、动态规划法,时间复杂度为O(n),空间复杂度为O(n)

利用一维数组逆向求解,求最长合法匹配的长度。

假设输入字符串S,长度为n。维护一个长度为n的一维数组dp[n],初始化值为0

dp[i]表示从S[I]S[n-1],包含S[i]的最长有效匹配括号子串长度。

则:

dp[n-1]=0;

i=n-2逆向求dp[i],并记录最大值。若S[i]==’(’,要想计算dp[i]的值,计算在S中,从i开始到n-1的子串。分两步计算:

STEP1:在S中寻找从i+1开始的有效括号匹配字串长度,即dp[i+1]。跳过此段已经匹配的子串,查看下一个字符,其下标为j=i+1+dp[i+1]。若j未越界,并且S[j]==’)’,则s[i,...j]为有效匹配的子串,即dp[i]=dp[i+1]+2

STEP2:求得匹配子串S[i,...j]之后,若j+1未越界,则dp[i]的值还要加上从j+1开始的最长有效匹配。即dp[j+1]

 

class Solution
{
public:
  int max(int a,int b)
  {
    return a>b?a:b;
  }
  int longestValidParentheses(string s)
  {
    int n=s.size();
	if(n<2) return 0;
	
	int dp[n];//动态规划
	for(int i=0;i<n;i++)
	  dp[i]=0;//初值为0
	  
	int maxlen=0;
	for(int i=0;i<s.size();i++)
	{
	  if(s[i]=='(')
	  {
	    int j=i+1+dp[i+1];
		if(j<n&&s[j]==')')
		{
		  dp[i]=dp[i+1]+2;
		  
		  if(j+1<len)
		    dp[i]+=dp[j+1];
		}
	  }
	  //更新匹配最长字串长度
	  maxlen=max(maxlen,dp[i]);
	}
	return maxlen;
  }
  
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值