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 <= 8When 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 approach to generating valid parentheses involves creating every possible combination of opening and closing parentheses and then checking each one to see if it's valid. It's like trying out every single arrangement of building blocks before finding the ones that form a stable structure.
Here's how the algorithm would work step-by-step:
def generate_parenthesis_brute_force(number_of_pairs):
all_parentheses_combinations = []
final_valid_parentheses = []
def generate_all_combinations(current_combination):
if len(current_combination) == 2 * number_of_pairs:
all_parentheses_combinations.append("".join(current_combination))
return
current_combination.append('(')
generate_all_combinations(current_combination)
current_combination.pop()
current_combination.append(')')
generate_all_combinations(current_combination)
current_combination.pop()
def is_valid_parentheses(parentheses_string):
balance_counter = 0
# This check ensures we never have more closing than opening parentheses at any point.
for character in parentheses_string:
if character == '(':
balance_counter += 1
else:
balance_counter -= 1
if balance_counter < 0:
return False
# This check ensures that the total number of opening and closing parentheses are equal.
return balance_counter == 0
generate_all_combinations([])
# Iterate through all generated combinations to filter out invalid ones.
for combination in all_parentheses_combinations:
if is_valid_parentheses(combination):
final_valid_parentheses.append(combination)
return final_valid_parenthesesThis problem is about building valid arrangements of parentheses. The best way to do this is to think about it as a process of making choices step by step, ensuring that at each point, the choices we make are valid and lead us towards a complete, correct arrangement.
Here's how the algorithm would work step-by-step:
def generate_parenthesis_combinations(maximum_pairs):
all_valid_combinations = []
def backtrack_parentheses(current_string, open_count, close_count):
# Base case: If the current string is complete, add it to results.
if len(current_string) == maximum_pairs * 2:
all_valid_combinations.append(current_string)
return
# Rule: Can add an opening parenthesis if we haven't used all available.
if open_count < maximum_pairs:
backtrack_parentheses(current_string + '(', open_count + 1, close_count)
# Rule: Can add a closing parenthesis if it matches an open one.
if close_count < open_count:
backtrack_parentheses(current_string + ')', open_count, close_count + 1)
backtrack_parentheses('', 0, 0)
return all_valid_combinations| Case | How to Handle |
|---|---|
| n = 0 (zero pairs of parentheses) | The algorithm should return a list containing a single empty string, representing no parentheses. |
| n = 1 (one pair of parentheses) | The algorithm should correctly generate and return a list containing only '()'. |
| Large values of n | For very large n, the number of combinations grows exponentially, potentially leading to performance issues (time complexity) and memory constraints. The recursive backtracking approach is generally efficient for reasonable n. |
| Negative input for n | The problem statement implies n is a non-negative integer; a negative n should ideally result in an empty list or an error, as it's an invalid input for the number of pairs. |
| Non-integer input for n | The problem specifies an integer n; non-integer inputs are out of scope and should be handled by input validation if necessary. |
| Maximum recursion depth exceeded for very large n | If n is extremely large, a recursive solution might hit the maximum recursion depth limit of the language, requiring an iterative approach or increasing the recursion limit if feasible. |
| No valid combinations exist (though not possible for n >= 0) | For n >= 0, there will always be at least one valid combination (the empty string for n=0) or multiple combinations for n > 0. |
| Multiple valid solutions are possible | The core requirement of the problem is to generate ALL valid combinations, so the algorithm must be designed to explore all valid paths to produce them. |