Given a string containing just the characters '('
and ')'
, return the length of the longest valid (well-formed) parentheses substring.
Example 1:
Input: s = "(()" Output: 2 Explanation: The longest valid parentheses substring is "()".
Example 2:
Input: s = ")()())" Output: 4 Explanation: The longest valid parentheses substring is "()()".
Example 3:
Input: s = "" Output: 0
Constraints:
0 <= s.length <= 3 * 104
s[i]
is '('
, or ')'
.This problem asks to find the length of the longest valid (well-formed) parentheses substring within a given string containing only '(' and ')'.
This approach uses dynamic programming to build a DP array f
where f[i]
represents the length of the longest valid parentheses substring ending at index i
.
Algorithm:
Initialization: Create a DP array f
of size n+1
(where n
is the length of the string) and initialize all elements to 0. This handles edge cases of empty or single-character strings.
Iteration: Iterate through the string from index 1 (second character):
s[i-1]
is ')', check the previous character s[i-2]
:
s[i-2]
is '(', it means we found a valid pair "()". The length of the longest valid substring ending at i
is f[i] = f[i-2] + 2
.s[i-2]
is ')', we need to look further back. Let j = i - f[i-1] - 1
. If j
is a valid index and s[j-1]
is '(', then we found a longer valid substring. The length becomes f[i] = f[i-1] + 2 + f[j-1]
. This accounts for potentially nested valid substrings.Result: The maximum value in the f
array represents the length of the longest valid parentheses substring.
Time Complexity: O(n) - Single pass through the string.
Space Complexity: O(n) - For the DP array f
.
This approach utilizes a stack to track the indices of opening parentheses.
Algorithm:
Initialization: Initialize a stack stack
with -1 (to handle edge cases) and a variable ans
to 0 (to store the maximum length).
Iteration: Iterate through the string:
i - stack[-1]
(current index minus the index of the matching '(') and update ans
if necessary.Result: ans
holds the length of the longest valid parentheses substring.
Time Complexity: O(n) - Single pass through the string. Space Complexity: O(n) - In the worst case (all opening parentheses), the stack can store all indices.
Approach 1 (Dynamic Programming):
class Solution:
def longestValidParentheses(self, s: str) -> int:
n = len(s)
f = [0] * (n + 1)
for i in range(2, n + 1):
if s[i - 1] == ')':
if s[i - 2] == '(':
f[i] = f[i - 2] + 2
else:
j = i - f[i - 1] - 1
if j > 0 and s[j - 1] == '(':
f[i] = f[i - 1] + 2 + f[j - 1]
return max(f)
Approach 2 (Using Stack):
class Solution:
def longestValidParentheses(self, s: str) -> int:
stack = [-1]
ans = 0
for i, c in enumerate(s):
if c == '(':
stack.append(i)
else:
stack.pop()
if not stack:
stack.append(i)
else:
ans = max(ans, i - stack[-1])
return ans
Both approaches have the same time and space complexity. The stack-based approach might be slightly easier to understand conceptually for some, while the dynamic programming approach might be preferred by others due to its straightforward iterative nature. The choice depends on personal preference and coding style.