Generate Parentheses
DESCRIPTION (credit Leetcode.com)
Given an integer n, write a function to return all well-formed (valid) expressions that can be made using n pairs of parentheses.
EXAMPLES
Example 1:
Input:
n = 3
Output:
["((()))","(()())","(())()","()(())","()()()"]
Example 2:
Input:
n = 2
Output:
["()()", "(())"]
Run your code to see results here
Explanation
Let's start by figuring out how to incrementally generate all valid combinations of n pairs of parentheses starting from an empty string s = "". Doing so will help us visualize the "solution space tree" which we can then traverse using a recursive backtracking approach.
At each step below, we can add either an opening parenthesis '(' or a closing parenthesis ')' to the string s as long as the resulting string remains valid. Let's walkthrough the process of generating all valid combinations of parentheses for n = 2:
s = ``
If we start with an empty string, then we can only add an opening parenthesis '(', as adding a closing parenthesis ')' would result in an invalid combination.
s = (
We can add both an opening parenthesis '(' and a closing parenthesis ')' to the string s without making it invalid.
s = (( and s = ()
For this string s = ((: we can't add an opening parenthesis '(' to s as it would make it invalid. This is because the number of opening parentheses is already equal to n. However, we can add a closing parenthesis ')' to s.
For the string s = (): we can only add an opening parenthesis '(' as adding a closing parenthesis would make it invalid. This is because s has an equal number of opening and closing parentheses, and we need to add another opening parenthesis before we can add a closing parenthesis.
From this, we can notice two rules:
- We can add an opening parenthesis '(' if the number of opening parentheses in s is less than n.
- We can add a closing parenthesis ')' if the number of closing parentheses in s is less than the number of opening parentheses in s.
s = (() and s = ()(
For the string s = ((): we can only add a closing parentheses ')' (since there are already n = 2 opening parentheses in s)
For the string s = ()(: we can only add a closing parentheses ')' (since there are already n = 2 opening parentheses in s)
s = (()) and s = ()()
In both cases, the length of the string s is equal to 2 * n, so we are done.
If we visualize this process as a tree, we get the following:
Writing the Backtracking Function
Once we have this tree, we can use depth-first search to write a recursive backtracking function that generates all valid combinations of n pairs of parentheses.
At each node, we need the current string, and the number of opening and closing parentheses in the string. These are the parameters we'll pass to our recursive function.
def dfs(s, open, close):
At each node, we'll make recursive calls to our left child if the number of opening parentheses is less than n, and to our right child if the number of closing parentheses is less than the number of opening parentheses.
def dfs(s, open, close):# base caseif open < n:# add an opening parenthesis and increment the open countdfs(s + '(', open + 1, close)if close < open:# add a closing parenthesis and increment the close countdfs(s + ')', open, close + 1)
The base case is when the length of the string is equal to 2 * n, at which point we'll add the string to our list of valid combinations.
def dfs(s, open, close):# base caseif len(s) == 2 * n:res.append(s)returnif open < n:# add an opening parenthesis and increment the open countdfs(s + '(', open + 1, close)if close < open:# add a closing parenthesis and increment the close countdfs(s + ')', open, close + 1)
In the main function, we'll initialize an empty list to store the valid combinations, and make the initial call to our recursive function with an empty string and counts of 0 for both opening and closing parentheses, and return the list of valid combinations at the end.
class Solution:def generateParenthesis(self, n: int) -> List[str]:res = []def dfs(s, open, close):# base caseif len(s) == 2 * n:res.append(s)returnif open < n:# add an opening parenthesis and increment the open countdfs(s + '(', open + 1, close)if close < open:# add a closing parenthesis and increment the close countdfs(s + ')', open, close + 1)dfs('', 0, 0)return res
Loading comments...