LeetCode 32. 最长有效括号--思维,合并

给定一个只包含 ‘(’ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。

示例 1:

输入: “(()”
输出: 2
解释: 最长有效括号子串为 “()”

示例 2:

输入: “)()())”
输出: 4
解释: 最长有效括号子串为 “()()”

通过次数59,468
提交次数194,425

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-valid-parentheses
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:
首先考虑题目要求的答案,就是找到最大子串,而且这个字串符合括号匹配原则,那么这样考虑,任何复杂的一串括号,都有最原子括号形式,就是’()’,任何复杂的括号都是这个延申出来的,比如给一个(),我再添加它的兄弟变成了()(),感觉他们暴露在外面不太好,我加个壳变成了(()()),然后又遇到一个新兄弟->(()())(),于是这样演变下去,可以看出来,任何复杂的但是符合条件的括号字符串,都是由单一的()经过两种方式演变来的,要么遇到自己的兄弟,要么被包围起来,于是我们处理的时候就可以先从左往右遍历每个(),然后发现()的左边也有(),就合并起来成()(),那么此时呢?我还可以再判断呀,因为()()是符合条件的,我再判断是否有外壳包围起来,或者左边还没有这样的兄弟,如果没有了继续往下,突然就遇到一个新的()马上再往左边看,看到了()(),太棒了,马上连接起来成了()()(),但是你怎么快速可以看到左边的()()呢?这个需要我们标记一下啦,我们不管结构,但凡是符合条件的子串,也就是不管是(())还是()()这样的结构,我们用sign定位到最右边的位置,然后vis[sign]就表示最左边的位置,这样判断就很方便啦。

AC代码

class Solution {
public:
int longestValidParentheses(string s) 
{
	int vis[1000000];
	memset(vis,-1,sizeof(vis));
	for(int i=0;i<s.length();i++)
	{
		if(s[i]=='('&&i+1<s.length()&&s[i+1]==')')
		{
			//标记定位到最左边 	
			vis[i+1]=i;
			//sign永远指向最右边 
			int sign=i+1;
			while(true)
			{
				bool flag=true;
				//表示左边的可以合并 
				//比如()(())->此时sign=5,vis[sign]=2,才能判断 
				if(vis[sign]-1>=0&&vis[vis[sign]-1]>=0)
				{
					flag=false;
					vis[sign]=vis[vis[sign]-1];
				}
				//包起来战略 
				if(sign+1<s.length()&&s[sign+1]==')'&&(vis[sign]-1>=0)&&s[vis[sign]-1]=='(')
				{
					flag=false;
					vis[sign+1]=vis[sign]-1;
					//移到最右边 
					sign=sign+1;
				}
				//已经不可再更新了 
				if(flag)
				break;
			}
		}	
	}
	int ans=0;
	for(int i=0;i<s.length();i++)
	{
		if(vis[i]==-1)continue;
		ans=max(ans,i-vis[i]+1); 	
	}  
	return ans;
}
};

希望我的分享对你的学习有所帮助,如有问题请及时指出,谢谢~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值