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 * 10^4 s[i] is '(' or ')'.
Could you describe an algorithm to solve this problem efficiently? What is the time and space complexity of your solution? Can you identify any edge cases and how your solution handles them?
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method for finding the longest valid parentheses works by checking every single possible substring within the given string. We want to see if that substring contains a balanced arrangement of open and close parentheses. We'll keep track of the longest one we find.
Here's how the algorithm would work step-by-step:
def longest_valid_parentheses_brute_force(parentheses_string):
max_length = 0
string_length = len(parentheses_string)
for start_index in range(string_length):
for end_index in range(start_index, string_length):
substring = parentheses_string[start_index:end_index + 1]
# We want to check if this substring is valid
if is_valid_parentheses(substring):
substring_length = len(substring)
# Keep track of the longest valid substring seen so far
max_length = max(max_length, substring_length)
return max_length
def is_valid_parentheses(substring):
stack = []
for char in substring:
if char == '(':
stack.append(char)
elif char == ')':
if stack and stack[-1] == '(':
stack.pop()
else:
return False
# Check that stack is empty at end to be valid
return not stack
The most efficient way to find the longest valid parentheses sequence is to scan the input string twice. The first scan goes from left to right, and the second goes from right to left, both using counters to keep track of open and closed parentheses.
Here's how the algorithm would work step-by-step:
def longest_valid_parentheses(input_string):
longest_length = 0
open_parentheses_count = 0
closed_parentheses_count = 0
# Scan from left to right
for character in input_string:
if character == '(':
open_parentheses_count += 1
else:
closed_parentheses_count += 1
# Reset if closed exceed open
if closed_parentheses_count > open_parentheses_count:
open_parentheses_count = 0
closed_parentheses_count = 0
if open_parentheses_count == closed_parentheses_count:
longest_length = max(longest_length, 2 * open_parentheses_count)
open_parentheses_count = 0
closed_parentheses_count = 0
# Scan from right to left
for character in reversed(input_string):
if character == '(':
open_parentheses_count += 1
else:
closed_parentheses_count += 1
# Reset if open exceed closed
if open_parentheses_count > closed_parentheses_count:
open_parentheses_count = 0
closed_parentheses_count = 0
# Update when counts are equal
if open_parentheses_count == closed_parentheses_count:
longest_length = max(longest_length, 2 * open_parentheses_count)
return longest_length
Case | How to Handle |
---|---|
Null or empty string input | Return 0, as an empty string contains no valid parentheses. |
String with only one character | Return 0, as a single character cannot form a valid pair. |
String with no valid parentheses (e.g., ')))') | The algorithm should correctly return 0, indicating no valid substring was found. |
String with only open parentheses (e.g., '(((((') | The algorithm should correctly return 0, indicating no valid substring was found. |
Maximum length string (consider memory constraints) | The algorithm needs to use O(n) space, so be mindful of potential memory limits if the input string is extremely large. |
String with deeply nested valid parentheses (e.g., '((((...))))') | The stack-based or dynamic programming approach must handle potentially deep nesting without causing stack overflow or integer overflow issues during length calculation. |
String with a long valid sequence at the beginning | The algorithm needs to correctly identify and track the longest valid substring and update the maximum length accordingly. |
String with alternating '(' and ')' but no valid consecutive pairs (e.g., '()()()') | The algorithm must handle this by properly calculating lengths after finding valid pairs, potentially needing to consider non-contiguous valid sequences. |