难度:困难
给定一个只包含 '('
和 ')'
的字符串,找出最长的包含有效括号的子串的长度。
示例 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;
}
};