Given n
pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
Example 1:
Input: n = 3 Output: ["((()))","(()())","(())()","()(())","()()()"]
Example 2:
Input: n = 1 Output: ["()"]
Constraints:
1 <= n <= 8
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 problem asks us to find all the correctly formed combinations of parentheses for a given number of pairs. The brute force method is like trying every single possible arrangement of open and close parentheses and then checking each one to see if it's a valid combination.
Here's how the algorithm would work step-by-step:
class Solution:
def generateParenthesis(self, number_of_pairs: int) -> list[str]:
all_possible_sequences = []
total_length = 2 * number_of_pairs
def generate_all_sequences(current_sequence):
# Once the sequence reaches the target length, we stop this path and store the result.
if len(current_sequence) == total_length:
all_possible_sequences.append("".join(current_sequence))
return
# Explore adding an open parenthesis to the current sequence.
current_sequence.append('(')
generate_all_sequences(current_sequence)
current_sequence.pop()
# Explore adding a close parenthesis to the current sequence.
current_sequence.append(')')
generate_all_sequences(current_sequence)
current_sequence.pop()
def is_combination_valid(sequence_to_check: str) -> bool:
balance_counter = 0
for character in sequence_to_check:
if character == '(':
balance_counter += 1
else:
balance_counter -= 1
# A negative balance means a closing parenthesis appeared without a matching open one.
if balance_counter < 0:
return False
# A valid combination must end with a zero balance, meaning equal open and close counts.
return balance_counter == 0
generate_all_sequences([])
valid_combinations = []
for sequence in all_possible_sequences:
if is_combination_valid(sequence):
valid_combinations.append(sequence)
return valid_combinations
To generate all valid combinations of parentheses, we can think of it as building them one character at a time. The key is to follow two simple rules at each step to ensure we only build valid sequences, avoiding the need to check them for correctness at the end.
Here's how the algorithm would work step-by-step:
class Solution:
def generateParenthesis(self, number_of_pairs: int) -> list[str]:
valid_combinations = []
def build_combinations(current_string, open_parentheses_needed, close_parentheses_needed):
# A combination is complete and valid when it reaches the target length.
if len(current_string) == 2 * number_of_pairs:
valid_combinations.append(current_string)
return
# Rule 1: We can add an opening parenthesis if we still have some left to place.
if open_parentheses_needed > 0:
build_combinations(current_string + '(', open_parentheses_needed - 1, close_parentheses_needed)
# Rule 2: We can add a closing parenthesis only if it doesn't exceed the open ones.
if close_parentheses_needed > open_parentheses_needed:
build_combinations(current_string + ')', open_parentheses_needed, close_parentheses_needed - 1)
# Start the recursive process with an empty string and the total counts for n pairs.
build_combinations("", number_of_pairs, number_of_pairs)
return valid_combinations
Case | How to Handle |
---|---|
Input n = 0 | The solution should return a list containing a single empty string, representing zero pairs of parentheses. |
Input n = 1 | The base case for recursion should correctly produce a list with the single valid combination "()". |
Negative input for n (e.g., n = -1) | The function should return an empty list as no well-formed parentheses can be generated for a negative number of pairs. |
Large input for n (e.g., n = 10 or more) | The number of solutions grows exponentially (Catalan numbers), so the solution must be efficient to avoid timeouts and manage memory. |
Recursive solution stack depth | The maximum recursion depth will be 2*n, which is well within typical stack limits for reasonable constraints on n. |
Intermediate string states that are not well-formed | The backtracking algorithm's constraints must ensure that the number of closing parentheses never exceeds the number of opening parentheses at any point. |
Non-integer input for n (e.g., float, string) | Depending on the language, this might raise a type error or require explicit type checking to handle gracefully. |
Final validation of parentheses count | The algorithm must ensure that each valid final string contains exactly n opening and n closing parentheses. |