【leetcode】String——Longest Valid Parentheses(32)

题目:

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:新建一个标记数组,标记s中匹配的位置,最后判断最长连续出现的标记。 时间复杂度:O(n)

代码1:

第一次提交:超时了

   public int longestValidParentheses(String s) {
        
    	int[]flag = new int[s.length()];
    	
    	Stack<Character> stack = new Stack<Character>();
    	Stack<Integer> stackIndex = new Stack<Integer>();
    	char[] cc = s.toCharArray();
    	for(int i=0;i<cc.length;i++){
    		if(stack.isEmpty()){
    			stack.push(cc[i]);
    			stackIndex.push(i);
    		}
    		else if(cc[i]=='('){
    			stack.push(cc[i]);
    			stackIndex.push(i);
    		}
    		else if(cc[i]==')'){
    			if(stack.peek()=='('){  //match
    				stack.pop();
    				flag[i]=1;
    				flag[stackIndex.pop()]=1;
    			}else if(stack.peek()==')'){  //not match
    				stack.push(cc[i]);
        			stackIndex.push(i);
    			}
    		}
    	}
    	
    	int maxLen = 0;
    	int curLen = 0;
    	for(int i=0;i<s.length();i++){
    		if(flag[i]==1){
    			curLen++;
    			maxLen = Math.max(maxLen, curLen);
    		}else{
    			curLen=0;
    		}
    	}
    	return maxLen;
    
    }
借鉴网上帖子优化了自己的算法:

因为要记录匹配上的位置,所以,异常的情况可以不入stack,比如出现)且stack为空。

其实算法还可以优化,不需要stack,只需要stackIndex即可。

public int longestValidParentheses(String s) {
	int[]flag = new int[s.length()];
	
	Stack<Character> stack = new Stack<Character>();
	Stack<Integer> stackIndex = new Stack<Integer>();
	char[] cc = s.toCharArray();
	for(int i=0;i<cc.length;i++){
		if(cc[i]=='('){
			stack.push(cc[i]);
			stackIndex.push(i);
		}
		else if(cc[i]==')'&&!stack.isEmpty()){
				stack.pop();
				flag[i]=1;
				flag[stackIndex.pop()]=1;
		}
	}
	
	int maxLen = 0;
	int curLen = 0;
	for(int i=0;i<s.length();i++){
		if(flag[i]==1){
			curLen++;
			maxLen = Math.max(maxLen, curLen);
		}else{
			curLen=0;
		}
	}
	return maxLen;
}

思路2:动态规划。逆向的dp。dp[s.length]=0; dp[i]  i:s.length-2~0  

dp[i]记录从i开始(包含i),到s末尾,最长匹配的长度。

如果i位置是),dp[i]=0;

 如果是(,在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]。

代码2:

public int longestValidParentheses_dp(String s){
	if(s.equals(""))
		return 0;
	int max =0;
	int dp[] = new int[s.length()];
	dp[s.length()-1]=0;
	for(int i=s.length()-2;i>=0;i--){
		if(s.charAt(i)=='('){
			int j=i+1+dp[i+1];
			if(j<s.length()){
				if(s.charAt(j)==')'){
					dp[i] = dp[i+1]+2;
					if(j+1<s.length()){
						dp[i]+=dp[j+1];
					}
				}
			}
			
		}
		max = Math.max(max, dp[i]);
	}
	
	
	return max;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值