Leetcode 32. Longest Valid Parentheses
Find the length of the longest well-formed (balanced) parentheses substring in a string of '(' and ')', handling nested and adjacent valid segments; this typically requires tracking matching positions or lengths (e.g., via a stack, dynamic programming, or a two-pass counter scan) to do efficiently.
Asked at:
Meta
DESCRIPTION
Find the length of the longest well-formed (balanced) parentheses substring in a string of '(' and ')', handling nested and adjacent valid segments; this typically requires tracking matching positions or lengths (e.g., via a stack, dynamic programming, or a two-pass counter scan) to do efficiently.
Input:
s = "((()"
Output:
2
Explanation: The longest valid parentheses substring is "()", which has length 2
Constraints:
- 0 <= s.length <= 3 * 10^4
- s[i] is '(' or ')'
- Must find contiguous substring (cannot skip characters)
Understanding the Problem
Let's understand what we're being asked to do. Given a string like '(()', we need to find the length of the longest substring where parentheses are properly balanced.
Tracing through '(()': The substring '()' at the end is balanced (length 2), but the full string is not balanced because there's an extra '(' at the start. So the answer is 2.
For '()(()', we have '()' at the start (length 2) and '()' at the end (length 2), but they're separated by an unmatched '('. The longest single balanced substring is 2.
Important constraint: We need a contiguous substring that is well-formed. We can't skip characters or combine non-adjacent valid segments.
Edge cases to consider: What if the entire string is balanced like '(())'? (return the full length). What if no valid substring exists like '((('? (return 0). What about empty string? (return 0).
Brute Force Approach
The brute force approach checks every possible substring to see if it's balanced. For each starting position, try all ending positions and validate if that substring has matching parentheses. This requires checking if opening and closing counts match and that closing never exceeds opening at any point. While simple to understand, this approach is very inefficient as it examines all possible substrings.
def longest_valid_parentheses(s):"""Brute force approach: Check every possible substring to see if it's balanced.For each starting position, try all ending positions and validate if thatsubstring has matching parentheses."""max_length = 0n = len(s)# Try every possible starting positionfor start in range(n):# Try every possible ending position from this startfor end in range(start + 2, n + 1, 2): # Only even-length substrings can be valid# Extract substringsubstring = s[start:end]# Check if this substring is valid (balanced parentheses)if is_valid_parentheses(substring):# Update max length if this valid substring is longermax_length = max(max_length, end - start)return max_lengthdef is_valid_parentheses(s):"""Helper function to check if a string has balanced parentheses.Returns True if opening and closing counts match and closing never exceeds opening."""open_count = 0# Scan through each characterfor char in s:if char == '(':# Increment count for opening parenthesisopen_count += 1elif char == ')':# Decrement count for closing parenthesisopen_count -= 1# If closing exceeds opening at any point, it's invalidif open_count < 0:return False# Valid only if all opening parentheses are matchedreturn open_count == 0
Start brute force: check every possible substring
0 / 35
Test Your Knowledge
Login to take the complexity quiz and track your progress
Complexity Analysis
Time Complexity: O(n^3) We have O(n^2) possible substrings, and validating each substring takes O(n) time to check if it's balanced
Space Complexity: O(1) We only use a constant amount of extra space for counters during validation
Building Intuition
A balanced substring has the property that at any point while reading left-to-right, the number of closing parentheses never exceeds the number of opening parentheses.
Additionally, at the end of a valid substring, the counts must be exactly equal. This means we need to track both the positions and the matching relationships.
Simply counting opening and closing parentheses isn't enough because '())()' has equal counts but isn't one valid substring.
We need to know where valid segments start and end. When we encounter a closing ')' that matches an opening '(', we can calculate the length of the valid substring ending at that position.
Think about checking if parentheses match: when you see '(', you're waiting for a future ')' to close it. When you see ')', you need to find its matching '('.
If we track the positions of unmatched opening parentheses, then when we see a closing parenthesis, we can find its match and calculate the length of the valid segment. The challenge is handling nested structures like '((()))' and adjacent segments like '()()'.
Common Mistakes
Optimal Solution
The optimal approach uses a stack to track the indices of unmatched parentheses. We push the index of each '(' onto the stack. When we see ')', we pop from the stack (matching it with the most recent unmatched '('). The key insight is maintaining a base index on the stack to calculate lengths: the current index minus the top of the stack gives us the length of the current valid substring. This efficiently handles both nested structures like '((()))' and adjacent segments like '()()'.
def longest_valid_parentheses(s):"""Find the length of the longest valid (well-formed) parentheses substring.Uses a stack to track indices of unmatched parentheses."""# Initialize stack with base index -1stack = [-1]max_length = 0# Iterate through each character with its indexfor i in range(len(s)):if s[i] == '(':# Push index of '(' onto stackstack.append(i)else:# Pop from stack for ')'stack.pop()if not stack:# Stack empty: current ')' is unmatched, push as new basestack.append(i)else:# Calculate length: current index - top of stackcurrent_length = i - stack[-1]max_length = max(max_length, current_length)return max_length
Start: Find longest valid parentheses substring
0 / 15
Test Your Knowledge
Login to take the complexity quiz and track your progress
Complexity Analysis
Time Complexity: O(n) We scan through the string once, performing constant-time operations (push/pop) for each character
Space Complexity: O(n) In the worst case (all opening parentheses), the stack stores all n indices
What We've Learned
- Stack for position tracking: Use a stack to store indices (not characters) of parentheses - this allows you to calculate substring lengths by subtracting indices when matches are found, which is essential for finding the longest valid segment rather than just validating balance.
- Base index technique: Initialize the stack with -1 as a base reference point before processing - this handles the edge case where valid parentheses start at index 0, allowing you to calculate length as (current_index - stack.top()) without special conditions.
- Match-and-calculate pattern: When encountering ')', pop the stack first, then check if it's empty - if empty, push current index as new base; if not empty, calculate length from remaining top. This single pattern handles both tracking invalid positions and computing valid lengths.
- Dynamic programming alternative: The DP approach uses dp[i] to store the longest valid length ending at position i - when you find ')', look back at dp[i-1] to skip over the inner valid substring and check if there's a matching '(' before it, then add any valid substring before that match.
- Two-pass counter optimization: Scanning left-to-right tracking open/close counts, then right-to-left achieves O(1) space - reset counters when close > open (or open > close in reverse), and record max when open == close. This works because each pass catches what the other misses in unbalanced scenarios.
- Substring vs subsequence distinction: This problem requires contiguous valid parentheses (substring), not just any valid pairing - that's why we track positions/lengths continuously and reset on invalid characters, rather than just counting matches like in simpler balance-checking problems.
Related Concepts and Problems to Practice
hard
This is the exact same problem as the one being analyzed. It directly practices finding the longest well-formed parentheses substring using stack-based techniques to track matching positions.
easy
This is a foundational problem for parentheses matching using stacks. It teaches the core pattern of using a stack to validate balanced parentheses, which is essential before tackling the longest valid substring variant.
Test Your Understanding
Why is stack the right data structure for this problem?
stack provides the optimal access pattern
It's the only data structure that works
It's the easiest to implement
It uses the least memory
Select an answer to see the explanation
Question Timeline
See when this question was last asked and where, including any notes left by other candidates.
Late November, 2025
Meta
Senior
Early November, 2025
Meta
Mid-level
return the longest valid parentheses substring, after asking clarifying questions the interviewer asked to return either the first longest valid substring or last but it should be deterministic.
Mid October, 2025
Meta
Staff
Given a string containing just the characters '(' and ')', return the length of the longest valid (well-formed) parentheses substring.
Comments
Hello Interview Premium
Your account is free and you can post anonymously if you choose.