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 goal is to generate all possible valid combinations of parentheses given a number 'n', where 'n' represents the number of pairs of parentheses. The brute force method involves creating every possible sequence of parentheses and then checking if each sequence is valid.
Here's how the algorithm would work step-by-step:
def generate_parentheses_brute_force(number_pairs):
all_combinations = []
def generate_all_sequences(current_string, string_length):
if len(current_string) == string_length:
all_combinations.append(current_string)
return
generate_all_sequences(current_string + '(', string_length)
generate_all_sequences(current_string + ')', string_length)
generate_all_sequences('', 2 * number_pairs)
valid_combinations = []
for combination in all_combinations:
if is_valid(combination):
valid_combinations.append(combination)
return valid_combinations
def is_valid(parentheses_string):
balance = 0
# Ensure that there isn't a closing parenthesis without a matching open parenthesis
for character in parentheses_string:
if character == '(':
balance += 1
else:
balance -= 1
if balance < 0:
return False
# Check to ensure an equal number of open/close parentheses.
if balance == 0:
return True
else:
return False
The most efficient way to generate valid parentheses combinations is to build them step-by-step, always maintaining a valid structure. We achieve this by tracking available open and closed parentheses, only adding them if they lead to a balanced state.
Here's how the algorithm would work step-by-step:
def generate_parenthesis(number):
results = []
def backtrack(current_string, open_count, close_count):
# Base case: if we've used all parentheses, add to results.
if open_count == number and close_count == number:
results.append(current_string)
return
# Add an open parenthesis if we have available open parentheses.
if open_count < number:
backtrack(current_string + '(', open_count + 1, close_count)
# Only add a closing parenthesis if it's valid.
if close_count < open_count:
backtrack(current_string + ')', open_count, close_count + 1)
# Initiate backtracking from an empty string
backtrack("", 0, 0)
return results
Case | How to Handle |
---|---|
n = 0 | Return an empty string or a list containing an empty string, as no parentheses are needed. |
n = 1 | Return a list containing only '()' as the only valid combination. |
Large n (e.g., n > 15) | The number of valid parentheses combinations grows exponentially, so the solution should be efficient in terms of memory and time complexity using backtracking or dynamic programming to avoid exceeding recursion depth limits and memory constraints. |
Negative input for n | Throw an exception or return an empty list, as the number of pairs cannot be negative. |
Non-integer input for n | Throw an exception, as the number of pairs must be an integer. |
Maximum recursion depth exceeded for very large n | Consider iterative dynamic programming as an alternative to recursion to avoid stack overflow. |
n is a floating point number | Cast n to integer type and proceed only if the value is positive; otherwise, handle it as invalid input. |
Solution produces duplicate parenthesis combinations | Ensure that the algorithm only adds valid combinations (balanced) and the data structure storing solutions like set can guarantee uniqueness. |