LeetCode-----第三十二题-----最长有效括号

最长有效括号

难度:困难

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

示例 1:

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

示例 2:

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

 

题目分析:

  本题有两种方案可以解答,时间复杂度和空间复杂度都为O(n)。一个是使用堆,另一个是使用DP。

  1.先分析一下DP问题。这里的DP比较复杂,分析一波:

   (1)查看是否是最优子问题和重叠子问题,明显符合条件。一个是找到现在之前最长有效括号,另一个是现在有效括号数与之前相加(这边可能不懂,后边就会懂)。

   (2)写出状态转移方程。从第二个字符开始遍历,先分为两种情况:

     i)不配对,f(i) = 0

     ii)配对(这里情况较为复杂,有两种情况)

       (I)类似于“(()”。当前位置的括号与前一个匹配,f(i) = f(i-2)+2

       (II)类似于“()((()))”。这样的情况就是f(i) = f(i-f(i-1)-1)+f(i-1)+2,这里比较容易分错。我们先对这个例子进行编号0~7。那么我们在分析第5括号时,这时是f(5)=f(5-f(4)-1)+f(4)+2。细品

参考代码:

#include "iostream"
#include "vector"
#include "string"
#include "unordered_map"
#include "deque"
#include "stack"
#include "algorithm"

using namespace std;

class Solution {
public:
	int longestValidParentheses(string s) {
		if (s.size() < 2)
			return 0;

		vector<int> f(s.length());
		int my_max = 0;
		for (int i = 1; i < s.size(); i++)
		{
			if (s[i] == ')')
			{
				if (s[i - 1] == '(')
				{
					f[i] = (i - 1) == 0 ? 2 : (f[i - 2] + 2);
				}
				else if ((i - f[i - 1] - 1) >= 0 && s[i - f[i - 1] - 1] == '(')
				{
					f[i] = ((i - f[i - 1] - 2) >= 0 ? f[i - f[i - 1] - 2] : 0) + f[i - 1] + 2;
				}
			}
			my_max = max(my_max, f[i]);
		}

		return my_max;
	}
};

int main()
{
	Solution solution;
	string str = "()(())";
	
	cout << solution.longestValidParentheses(str) << endl;

	system("pause");
	return 0;
}

 

参考代码:(使用栈)B站视频:https://www.bilibili.com/video/BV1e64y1T7Lc?from=search&seid=2022146288783722946

class Solution {
public:
    int longestValidParentheses(string s) {
        if(s.size() < 2)
            return 0;
        
        stack<int> stack_k;
        stack_k.push(-1);//先压入-1,便于计算

        int res = 0;
        for(int i = 0; i < s.size(); i++)
        {
            if(s[i] == '(')//遇到左括号,就把下标压入栈
               stack_k.push(i);
            else{
                stack_k.pop();//遇到右括号就出栈
                if(stack_k.empty())//当栈为空的时候,将当前下标压入栈
                    stack_k.push(i);
                
                res = max(res,i-stack_k.top());//取最大值
            }
        }

        return res;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值