class Solution:
def longestValidParentheses(self, s: str) -> int:
stack = [-1]
max_len = 0
for i, ch in enumerate(s):
if ch == '(':
stack.append(i)
else:
stack.pop()
if not stack:
stack.append(i)
else:
max_len = max(max_len, i - stack[-1])
return max_len
class Solution {
public:
int longestValidParentheses(string s) {
stack<int> stk;
stk.push(-1);
int maxLen = 0;
for (int i = 0; i < s.size(); ++i) {
if (s[i] == '(') {
stk.push(i);
} else {
stk.pop();
if (stk.empty()) {
stk.push(i);
} else {
maxLen = max(maxLen, i - stk.top());
}
}
}
return maxLen;
}
};
class Solution {
public int longestValidParentheses(String s) {
Stack<Integer> stack = new Stack<>();
stack.push(-1);
int maxLen = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(') {
stack.push(i);
} else {
stack.pop();
if (stack.isEmpty()) {
stack.push(i);
} else {
maxLen = Math.max(maxLen, i - stack.peek());
}
}
}
return maxLen;
}
}
var longestValidParentheses = function(s) {
let stack = [-1];
let maxLen = 0;
for (let i = 0; i < s.length; i++) {
if (s[i] === '(') {
stack.push(i);
} else {
stack.pop();
if (stack.length === 0) {
stack.push(i);
} else {
maxLen = Math.max(maxLen, i - stack[stack.length - 1]);
}
}
}
return maxLen;
};
Given a string s
consisting of only the characters '('
and ')'
, your task is to compute the length of the longest substring that forms a valid set of parentheses. A valid set of parentheses is one where every opening parenthesis '('
has a corresponding closing parenthesis ')'
in the correct order and properly nested.
s
can be empty or up to 30,000 characters long.s
is either '('
or ')'
.
Example: For s = "(()"
, the answer is 2
because "()"
is the longest valid substring.
The problem is essentially about matching parentheses, but not just checking if the whole string is valid; instead, we want the length of the longest valid substring. At first glance, one might consider checking all possible substrings and verifying if each is valid, but this would be extremely inefficient for long strings.
Recognizing that parentheses matching is a classic stack problem, we can use a stack to help us track the positions of unmatched parentheses. When we find a match, we can calculate the length of the current valid substring. Alternatively, we might consider dynamic programming, but the stack approach is often more intuitive and space-efficient for this problem.
The key insight is that by storing indices (not just characters) in the stack, we can easily compute the length of valid substrings when a match is found.
-1
. This acts as a "base" for the calculation of lengths and helps handle edge cases where the valid substring starts at the beginning.
s
character by character, tracking the current index i
.
'('
, push its index onto the stack.
')'
:
'('
if there is one).'('
for this ')'
.i - stack[-1]
(or i - stack.top()
in C++/Java). Update the maximum length if this is the largest seen so far.
This approach works because the stack always contains indices of unmatched '('
characters, and the base index for the start of the next potential valid substring.
Let's walk through the input s = ")()())"
step by step:
stack = [-1]
, max_len = 0
s[0] = ')'
:
-1
, stack is now empty.0
as new base, so stack = [0]
.s[1] = '('
:
1
, stack = [0, 1]
.s[2] = ')'
:
1
, stack = [0]
.2 - 0 = 2
, update max_len = 2
.s[3] = '('
:
3
, stack = [0, 3]
.s[4] = ')'
:
3
, stack = [0]
.4 - 0 = 4
, update max_len = 4
.s[5] = ')'
:
0
, stack is now empty.5
as new base, stack = [5]
.
The longest valid substring is ()()
from index 1 to 4, with length 4.
The key to solving the Longest Valid Parentheses problem efficiently is recognizing the usefulness of a stack for tracking unmatched parentheses and using indices to quickly compute substring lengths. By maintaining a base index and updating the maximum length found at each step, we avoid redundant checks and achieve a linear-time solution. This approach elegantly leverages classic stack mechanics to solve a tricky substring problem in a single pass.