最长有效括号

题目描述:

       给定只包含括号字符'('和 ')''的字符串,请找出最长的有效括号内子括号的长度。 举几个例子如下: 例如对于"( ()",最长的有效的括号中的子字符串是"()" ,有效双括号数1个,故它的长度为 2。  再比如对于字符串") () () )",其中最长的有效的括号中的子字符串是"() ()",有效双括号数2个,故它的长度为4。  再比如对于"( () () )",它的长度为6。换言之,便是有效双括号"()"数的两倍。 给定函数原型int longestValidParentheses(string s),请完成此函数,实现上述功能。                        

分析:这类题目,求最长的、最大的、最多的,一般都可以用贪心算法思想实现。尽可能的得到最优解。庞果里这道题目很容易令人误解,因为题目中没有说明有效括号是都连续的,所以有很多人第一时间会想到不是连续的,因此这样的想法纠错了。我刚开始也是这样想的,所以提交错了。在这个假期中,这些旧题就只能提交一次,如果以前提交了,那么现在就不能提交了,这个限制了我验证算法的真正确性。注:题目的有效括号是连续的。

      下面我就不连续、连续都将算法实现出来吧。这两个仅供参考,因为没有经实际题目提交验证过,所以有什么不对的,望各位帮忙指出!谢谢了!

  • 不连续的最长有效括号

    算法思想:

首先找到最左边的左括号s[i]='(',然后向后查找距离最近的右括号s[j]=')',(其中0<=i<j<n)。如果没有找到,即是s[j]='(',那么令i=j,同事j++。重复该步骤的去找出一对括号。如果找到了,则将计数counts+=2,并使用s[i]=s[j]='0'记录该括号已经使用,然后回溯i,直到s[i]='('为止,然后继续下一对括号寻找。直到i=len(s)为止,退出循环,返回最长有效括号数。

算法如下:

int longestValidParentheses(char *s)
{
	int i, j, k,counts=0;
	int len = strlen(s);
	for ( i = 0; i < len; i++)
	{
		if (s[i]=='(')
		{
			for (j = i; j < len; j++)
			{
				if (s[j]==')')
				{
					counts+=2;
					s[j] =s[i]= '0';
					while (s[i--]=='0' && i>=0){}
					break;
				}
				else if (s[j] == '(')
				{
					i = j;
				}
			}
		}
	}
	return counts;
}
  •      连续的有效括号长度

      算法思想:

    1. 首先去除无效的左边的右括号和无效的右边的左括号。
    2. 如果s[i]='(',那么左括号计数left+1,并且在left==0的时候记录下表k=i,以备以后回溯使用。
    3. 如果left>0并且s[i]=')',那么将右括号计数right+1,同时左括号计数left-1。
    4. 如果left==0并且s[i]==')'或者i==h,那么选择最长有效括号长度,即max=right>max?right:max;,接着将right清零,再回溯l=k。然后判断i是否等于h,如果是,则配对结束,否则继续回溯。
    5. 最后返回max*2即是最长有效括号长度。

     算法实现如下:

int longestValidParentheses(char *s)
{
	int i,k, l,h;
	int left = 0, right = 0, max = 0;
	l = -1;
	h = strlen(s);
	while (s[++l]==')' && l<h){}//去掉左边的右括号
	while (s[--h]== '(' && h>l){}//去掉左边的右括号
	for (i = l; i <= h; i++)
	{
		if (s[i] == '(') { if (left == 0) k = i;  left++; }
		if (left>0 && s[i] == ')') { right++; left--; }
		if ((left==0 && s[i]==')') || i==h)
		{
			if (right > max) max = right;
			right = 0;
			l = k;
			if (i == h)   break;
		}
	}
	return max*2;

}


   







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值