Medium Difficulty Question
The number n
represents how many pairs of brackets are generated. Please design a function, which is able to generate all possible valid parenthesis combinations.
E.g. 1:
Input: n = 3 Output: ["((()))","(()())","(())()","()(())","()()()"]
E.g. 2:
Input: n = 1 Output: ["()"]
where n>0
This is a combinatory problem. We notice that there's a bijection between the set of all valid brackets combinations and the set of all 2n-length Dyck Paths . Here's a graph to show how Bracket Sequences are matched with Dyck Paths.
Lemma 1: There's a mapping :→.
Proof: From left to right, a left bracket represents a upward step, while a right parenthesis represents an downward step. Since the combination is valid, we must.start from "(". Consider all subsequences that start from the first element, we can infer that the amounts of their left brackets must be greater than the right ones. This ensures the path always stays above the x-axis, and both the starting and ending y-coordinates are 0, as the brackets appear in pairs. Hence, is constructed, and all members is will be mapped into , with the help of .
Lemma 2: There also exists :→.
Proof: Clearly, the first step of a Dyck path must be an ascent (corresponding to a left parenthesis), and the last step must be a descent (corresponding to a right bracket). Denote as a function which makes the ups in one Dyck Path to left brackets, and the downs into right brackets. Let's prove that maps any element of to . Here, we use mathematical induction: it is clearly true for ( n=1 ). Assume it holds for ( n≤k ), and then prove it for ( n = k+1 ). First, classify the Dyck path based on the property that it always stays above the x-axis. A Dyck path either returns to the x-axis only at the last step or touches the x-axis multiple times. Consider the first point where the Dyck path touches the x-axis from left to right, and divide the path into two segments at this point.
It is easy to see that the second half is a Dyck path. Since the first half only touches the x-axis at its end, removing its first and last steps results in another Dyck path. This gives us the recursion of the Dyck path. By the induction hypothesis, the first half, after removing the first and last steps, corresponds to a valid bracket combination. Adding a left parenthesis at the beginning and a right parenthesis at the end of a valid combination is still valid, so the left half of the Dyck path corresponds to a valid bracket combination. The right half is already a valid bracket combination, so the entire path is valid. Therefore we finish the proof that maps everything in into by using induction.
Lemma 3: and . It's apparent, because of the definitions of .
Now the algorithm problem is transformed into solving all feasible Dyck Paths of length 2n. By using the recurrence relation of Dyck Path (see the Proof of Lemma 2), we can solve this problem recursively, generating all possible Dyck paths. The algorithm is shown as follows:
class Solution:
def generateParenthesis(self, n):
L = []
if n==0:
return ['']
else:
for i in range(1,n+1):
s = map(lambda x: "("+x+")", self.generateParenthesis(i-1))
for j in s:
L = L + list(map(lambda x: j+x, self.generateParenthesis(n-i)))
return L
The application of combinatorial mathematics and visual intuition in algorithm problems is elegent and inspiring.