题目描述:
给定只包含括号字符'('和 ')''的字符串,请找出最长的有效括号内子括号的长度。 举几个例子如下: 例如对于"( ()",最长的有效的括号中的子字符串是"()" ,有效双括号数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; }
-
连续的有效括号长度
算法思想:
-
首先去除无效的左边的右括号和无效的右边的左括号。
-
如果s[i]='(',那么左括号计数left+1,并且在left==0的时候记录下表k=i,以备以后回溯使用。
-
如果left>0并且s[i]=')',那么将右括号计数right+1,同时左括号计数left-1。
-
如果left==0并且s[i]==')'或者i==h,那么选择最长有效括号长度,即max=right>max?right:max;,接着将right清零,再回溯l=k。然后判断i是否等于h,如果是,则配对结束,否则继续回溯。
-
最后返回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; }