LeetCode Longest Valid Parentheses

本文介绍了一种高效算法来寻找给定字符串中最大长度的有效括号子串。通过正向与反向扫描,利用括号计数实现O(n)时间复杂度的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

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“)”-1,从头至尾叠加,如果和一直为正,最后等于0,则是合法的。这样不难想到一个n^2的暴力方法,当然,会超时。

 

O(n)的方法:

从头开始扫,保留头位置。暂存最大的合法串长度。

操作:

1、如果和等于0,则头到当前位置是合法的。

2、如果和小于0,则现在的头位置开始到尾必然不会有更长的合法串了。更改头位置,重置和。

3、如果和大于0,可能在之后出现更长的合法子串,继续。

 

那么一次扫描结束后,

1、如果和小于等于0,显然已经得到了最长的合法长度。

2、如果和大于0,则当时的头到尾之间可能存在合法串,且长度有可能大于已经获得最长长度。

 

截取尾部和为正的子串。

假设子串p是尾部和为正的子串的最长合法子串。

那么显然,它的开始位置必然不是0位置。先假设其后面有括号串。

那么有:

1p前面串的总和必然大于0,(如果等有等于0,则前面的是合法串,和p合并后可以产生更长的合法串)

2p前面的串的最后一个括号必然是"(",(否则由前1条观察可知:")"可以和之前的某个"("组成合法串,与p合并成更长和合法串)

3p后面的串综合必然大于等于0(否则由前2条观察知:p后面的串可以和前面的串的某部分匹配,从而形成更长的合法串)

4p后面的串的第一个必然是"("(否则由前3条观察可知:")"可以和前串的最后一个"("组成合法串,与p合并成更长和合法串)

 

因此可以从后向前扫描,以"("-1,以")"1,重复之前的操作,即可获得最长的合法串。

 

代码:

直接反转字符串反向扫描

class Solution {
public:
	int lvp(string s,int flag)	//括号串,正向反向标志
	{
		int ans=0;
		int len=s.size();
		if(len<2)
			return ans;
		int sum=0;
		int i=0,j=0;
		while(j<len)
		{
			if(s[j]=='(')
				sum+=flag;
			else
				sum-=flag;
			if(sum==0)
			{
				if(j-i+1>ans)
					ans=j-i+1;
			}
			else if(sum<0)
			{
				i=j+1;
				j=i;
				sum=0;
				continue;
			}
			j++;
		}
		return ans;
	}
    int longestValidParentheses(string s) {
        int l1=lvp(s,1);	//正向扫描
		reverse(s.begin(),s.end());	//反转
		int l2=lvp(s,-1);	//反向扫描
		return max(l1,l2);
    }
};


只计算尾部,速度略快:

class Solution {
public:
    int longestValidParentheses(string s) {
        int ans=0;
		int len=s.size();
		if(len<2)
			return ans;
		int sum=0;
		int i=0,j=0;
		while(j<len)	//正向扫描
		{
			if(s[j]=='(')
				sum++;
			else
			{
				sum--;
				if(sum==0)
				{
					if(j-i+1>ans)
						ans=j-i+1;
				}
				else if(sum<0)
				{
					i=j+1;
					j=i;
					sum=0;
					continue;
				}
			}
			j++;
		}
		if(j>=len&&j-i>ans)	//反向扫描尾部
		{
			sum=0;
			j=len-1;
			len=i;
			i=j;
			while(j>len)
			{
				if(s[j]==')')
					sum++;
				else
				{
					sum--;
					if(sum==0)
					{
						if(i-j+1>ans)
							ans=i-j+1;
					}
					else if(sum<0)
					{
						i=j-1;
						j=i;
						sum=0;
						continue;
					}
				}
				j--;
			}
		}
		return ans;
    }
};


 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值