689 words
3 minutes
最长有效括号

Cover Image Source: Source

题目链接:32. 最长有效括号

误入歧途#

本题一眼顶真,鉴定为动态规划,关键在于怎么动态规划。

一开始我的想法比较暴力,用一个二维数组f[n][n+1]来保存状态(实际用向量来实现)。其中f[i][j]表示从[i,j)[i, j)范围内的连续子串是否满足括号匹配规则( i=ji=j 时表示空串,此时f[i][j]值为true)。

对于一个合法的子串,一定以')'结尾。故合法子串可表示为 A(B)A(B) ,A和B均可为空串。对于每一个满足上式的子串,只需遍历所有的有序对 (A,B)(A, B) 即可判断是否是合法子串。转移方程如下:

f[i][j]={1,k[i,j1),s[i+k]=(f[i][k]f[i+k+1][j]0,0,otherwise.f[i][j]= \left\{ \begin{aligned} &1, & \sum_{k\in[i, j-1), s[i+k]='('}f[i][k]f[i+k+1][j] \neq 0, \\ &0, & otherwise. \end{aligned} \right.

代码如下

class Solution {
public:
int longestValidParentheses(string s) {
int n = s.length();
int maxn = 0;
vector<vector<int>> f(n, vector<int>(n + 1, 0));
for (int i = 0; i < n; ++i) f[i][0] = 1;
for (int j = 2; j <= n; j+=2)
for (int i = 0; i + j <= n; ++i)
if (s[i + j - 1] == ')')
for (int k = 0; k < j - 1; k+=2)
if (s[i + k] == '(' && f[i][k] && f[i + k + 1][j - k - 2]) {
f[i][j] = true;
maxn = j;
break;
}
return maxn;
}
};

时间复杂度为O(N3)O(N^3)。很不幸的是这个方法超时了。

另起炉灶#

重新思考后,我尝试了新的算法,将时间复杂度降到了 O(N)O(N) 。新的算法用一维数组dp[n+1]保存状态。其中dp[i]表示所有以第 i1i-1 个字符为结尾的合法子串中最长的子串的第一个字符的下标,即下标在 [dp[i],i)[dp[i], i) 中的所有字符组成一个合法子串且该子串无法向左扩充为新的子串。如果没有这样的子串,则dp[i]=idp[i] = i

沿用之前的思路,合法子串可表示为A(B)A(B)。当s[i-1]')'时,通过dp[i-1]可获取BB,若s[dp[i-1]-1]'(',则通过dp[dp[i-1]-1]可获取AA。转移方程如下:

dp[i]={dp[dp[i1]1],s[i1]=), dp[i1]0, [dp[i1]1]=(,i,otherwise.dp[i] = \left\{ \begin{aligned} & dp[dp[i-1]-1], & s[i-1]=')',\ dp[i-1]\neq 0,\ [dp[i-1]-1]='(', \\ & i, & otherwise. \end{aligned} \right.

代码如下:

class Solution {
public:
int longestValidParentheses(string s) {
int n = s.length();
int maxn = 0;
vector<int> dp(n + 1, 0); // dp[i]表示所有以第i-1个字符为结尾的合法子串中最长的子串的第一个字符的下标
for (int i = 0; i <= n; ++i) dp[i] = i;
for (int i = 2; i <= n; ++i) {
if (s[i - 1] != ')') continue;
if (dp[i - 1] == 0 || s[dp[i - 1] - 1] != '(') continue;
dp[i] = dp[dp[i - 1] - 1];
maxn = max(i - dp[i], maxn);
}
return maxn;
}
};

评测结果#

执行用时:4 ms, 在所有 C++ 提交中击败了77.37%的用户

内存消耗:7.2 MB, 在所有 C++ 提交中击败了21.63%的用户

通过测试用例:231 / 231

最长有效括号
https://etherwindy.github.io/AstroBlog/posts/leetcode-longest-valid-parentheses/
Author
etherwindy
Published at
2024-04-20
License
CC BY-NC-SA 4.0