Longest Valid Parentheses
Solution 1
这一题乍一看和“最长公共子序列”很像,我想了一会动态规划的状态方程,发现能力不行,于是就使用一个比较传统的栈的方式来处理括号,需要额外加一个调整:栈内保存的是对应符号的坐标。整个过程和验证序列有效性的思路类似:匹配则弹出,否则入栈,有效长度就计算弹出后栈顶的索引位置和当前位置的距离,此时二者之间的必然都是匹配完成的(有点贪心的思想)。因此判定逻辑为:
- 左括号,直接入栈
- 右括号需要进行检查:
- 如果当前栈为空,显然当前括号无效,入栈
- 如果当前栈不空,且栈顶可匹配,弹出后计算新栈顶的距离(需要处理一下此时栈内恰为空的结果)
- 如果栈不空,且栈顶不可匹配,继续入栈
- 时间复杂度: O ( N ) O(N) O(N), N N N为输入序列的长度
- 空间复杂度: O ( N ) O(N) O(N), N N N为输入序列的长度,主要是栈的实例化占用的空间
class Solution {
public:
int longestValidParentheses(string s) {
stack <int> check;
int ans = 0;
// /check.push(-1); // 最后恰好栈为空的情形
for (int i = 0; i < s.size(); ++i) {
// cout << s[i] << endl;
if (s[i] == '(') {
check.push(i);
}
else {
if (!check.empty() && s[check.top()] == '(') {
check.pop();
if (check.empty()) {
ans = max(ans, i + 1);
}
else {
ans = max(ans, i - check.top());
}
}
else {
check.push(i);
}
}
}
return ans;
}
};
Solution 2
官方给出的一种解决方法Longest Valid Parentheses - LeetCode,我没有想到,可以节省空间,实际上就是把栈的维护映射到两个变量上。基于题解的状态量设计,会存在漏检的情形,因此需要从左和从右分别遍历一次。
- 时间复杂度: O ( N ) O(N) O(N), N N N为输入序列的长度
- 空间复杂度: O ( 1 ) O(1) O(1),仅维护常数个状态量
class Solution {
public:
int longestValidParentheses(string s) {
int left = 0, right = 0, ans = 0;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(') {left++;}
else {right++;}
if (left == right) {
ans = max(ans, right * 2);
}
else if (right > left) {
left = right = 0;
}
}
left = 0, right = 0;
for (int i = s.size() - 1; i >= 0; --i) {
if (s[i] == '(') {left++;}
else {right++;}
if (left == right) {
ans = max(ans, left * 2);
}
else if (left > right) {
left = right = 0;
}
}
return ans;
}
};
Solution 3
Solution 1的Python实现
class Solution:
def longestValidParentheses(self, s: str) -> int:
check = list()
ans = 0
for i in range(len(s)):
# print(s[i], check)
if s[i] == '(': check.append(i)
else:
if len(check) > 0 and s[check[-1]] == '(':
check.pop()
if len(check) == 0: ans = max(ans, i + 1)
else: ans = max(ans, i - check[-1])
else:
check.append(i)
return ans
Solution 4
Solution 2的Python实现
class Solution:
def longestValidParentheses(self, s: str) -> int:
ans = 0
left, right = 0, 0
for i in range(len(s)):
if s[i] == '(': left += 1
else: right += 1
if left == right: ans = max(ans, right * 2)
elif right > left: left, right = 0, 0
left, right = 0, 0
for i in range(len(s) - 1, 0, -1):
if s[i] == '(': left += 1
else: right += 1
if left == right: ans = max(ans, left * 2)
elif left > right: left, right = 0, 0
return ans