题目: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.

村翻一下:给定一个只包含'('和')'的字符串,找出最长的括号匹配的子字符串。比如,“(()”,最长的子字符串为“()”,长度为2。再举个栗子,如“)()())”,最长的子字符串为"()()",长度为4。

 

这题最明显的方法就是搜索,时间复杂度为0(n^2)。明显的方法,肯定是会超时的-_-!

最开始的想法:

  我最开始的想法是,先定义一个栈,全部都保存的是'('(实际上这个栈不需要在代码里面用,只是想一下),遇到'(',那么就进栈,如果遇到’)‘并且栈不为空,那么就把括号长度cur加上1。如果遇到')'且栈为空,那么就让cur和max比较,如果比max大,那么就把max赋值为cur。整个方法中,其实不需要用栈,只需要记录'('的个数就可以了,因为整个栈中只有'("。但是这个方法有个漏洞,就是不能解决形如’(()(()'这样的括号字符串。按照前面的思路,这个字符串算出来的长度为4,所以上述方法是不行的。不过,这个给我提供了一个好的思路。

  使用一个数组。数组中的值为-1,0和子括号字符串的长度。子括号字符串的长度表示一个子括号字符串的长度。。。。-1表示某个位置上为一个')'且没有匹配上'('(如果匹配上的话,那么久会合并计入子括号字符串了)。0表示某个位置上为一个'('且没有任何匹配。比如s="(()(()"这个字符串,队列应该为[0, 2, 0, 2]。第一个0代表了s[0], 第一个2代表了第s[1]开始的“()”子字符串的长度,第二个0代表了s[3], 第二个2代表了第s[4]开始的"()"子字符串。所以该队列保存的就是'(',')'和匹配的子字符串的长度,不过’(‘长度算作0,')'算作-1。

  该算法这样运作。使用st记录'('的数目,esp为数组中最后一个元素的下标,a即为前边的数组。开始遍历整个字符串,如果遇到'(',那么就把0加到数组的尾部。如果遇到’)'且st>0,即前面有匹配的'(',那么就判断数组中最后一个元素是不是为0。如果为0,那么把数组最后一个元素赋值为2(这说明了当前的')'前面刚好是个'(')。如果不为0,那么把数组最后一个元素加二并赋值给倒数第二个元素,然后把最后一个元素弹出数组(这种情况对应了‘)’前面是“(()()”这种‘(’+合法子字符串的情况)。然后,赋值完以后,如果数组尾部的两个元素都不为0,那么就把两个值相加,然后赋值给倒数第二个元素(这代表了两个合法子字符串的合并)。

代码如下:

class Solution(object):
    def longestValidParentheses(self, s):
        """
        :type s: str
        :rtype: int
        """
        max = 0
        i = 0
        st = 0
        a =[]
        esp = -1

        for i in range(len(s)):
	    if (s[i] == '('):
		    a.append(0)
		    esp += 1
		    st += 1
	    elif ((s[i] == ')') & (st > 0)):#有匹配的'('
		    st -= 1
		    if (a[esp] == 0): #前边正好是')'
			    a[esp] = 2
		    elif ((esp > 0) and (a[esp] >= 0)): #前边是个合法的子字符串,再前边是匹配的'('
			    a[esp - 1] = a[esp] + 2
			    a.pop()
			    esp -= 1
		    else:#不可能的情况
			    print 'error\n'
			
		    if ((esp > 0) and (a[esp - 1]>0)): #合并合法的子字符串
			    a[esp-1] += a[esp]
			    a.pop()
			    esp -= 1
	    else:
		    a.append(-1)
		    esp += 1

        for i in a:
	        if (i > max):
		    max = i
	
        return max