Given n
pairs of parentheses, a function which returns the total number of all combinations well-formed parentheses could be:
def count_parenthesis(n, opened, closed):
if closed == n:
return 1
num_pairs = 0
if opened < n:
num_pairs += _count_parenthesis(n, opened + 1, closed)
if opened > closed:
num_pairs += _count_parenthesis(n, opened, closed + 1)
return num_pairs
Calling count_parentheses(3, 0, 0)
results in the following call tree:
count_parenthesis(2, 0, 0)
count_parenthesis(2, 1, 0)
count_parenthesis(2, 1, 1)
count_parenthesis(2, 2, 1)
count_parenthesis(2, 2, 2)
count_parenthesis(2, 2, 0)
count_parenthesis(2, 2, 1)
count_parenthesis(2, 2, 2)
How can the time and space complexity of this algorithm be determined?
There are a few areas which I'm unsure how to handle:
The variable that moves towards the base case (
closed == n
) does not get incremented every time.- Calls where a brace is opened (
opened + 1
) do not directly move towards the base case.
- Calls where a brace is opened (
There isn't an obvious relationship (IMO) between
n
and the number of well-formed combinations:
n = 3, f(n) = 5
n = 4, f(n) = 14
n = 5, f(n) = 42
n = 6, f(n) = 132
n = 7, f(n) = 429
n = 8, f(n) = 1430
I'm unsure how a recurrence relation can be defined when the base-case is not 1 or 0, but
n
?Should I approximate based on well-known runtime complexities? I.e. this looks like either exponential or factorial.
Note: I'm not looking for just an answer. I'd like to understand the process finding the time/space complexity for this type of recursive algorithm.