6
\$\begingroup\$

I had this question asked in an interview:

In how many ways, we can construct binary search tree from \$n\$ elements?

I have written this code, but got a feedback that it could be improved. How to do it?

def count_ways(n):
 c = [0] * (n+1)
 c[0] = 1
 c[1] = 1
 for i in xrange(2, n+1):
 sum_w = 0
 for j in xrange(0, i):
 sum_w += c[j] * c[i-j-1]
 c[i] = sum_w
 return c[n] 
print count_ways(4)
janos
113k15 gold badges154 silver badges396 bronze badges
asked Apr 22, 2017 at 16:12
\$\endgroup\$
0

3 Answers 3

7
\$\begingroup\$

The number of trees can be expressed in the closed form \$\frac{\binom{2n}{n}}{n+1}\,ドル and due to \$\binom{2n}{n} = \frac{4n - 6}{n} \binom{2(n-1)}{n-1}\$ the result is computed in linear time.

I would not ask such question in face-to-face interview (unless the position requires in-depth knowledge of combinatoric and graph theory).

answered Apr 22, 2017 at 18:45
\$\endgroup\$
1
  • \$\begingroup\$ Nice! Do you have a link to the explanation of the closed form? \$\endgroup\$ Commented Apr 23, 2017 at 5:40
2
\$\begingroup\$

The only optimization obvious to me is to reduce the number of iterations in the inner loop by the factor of two:

def count_ways_v2(n):
 c = [0] * (n + 1)
 c[0] = 1
 c[1] = 1
 for i in range(2, n + 1):
 sum_w = 0
 for j in xrange(0, i / 2):
 sum_w += 2 * c[j] * c[i - j- 1]
 if i % 2 == 1:
 sum_w += c[i / 2] * c[i / 2] # Handle the case in which i is odd:
 c[i] = sum_w
 return c[n]

Hope it helps.

Edit

@Peilonrayz suggests an improvement: your and mine versions run in quadratic time, yet via Catalan numbers you can do it in linear time:

def count_ways_catalan(n):
 a, b = 1, 1
 for k in range(2, n + 1):
 a *= n + k
 b *= k
 return a / b
Peilonrayz
44.4k7 gold badges80 silver badges157 bronze badges
answered Apr 22, 2017 at 16:43
\$\endgroup\$
1
  • \$\begingroup\$ Better yet, use math.factorial. The formula is \$\frac{(2n)!}{(n+1)!n!}\$. \$\endgroup\$ Commented Apr 22, 2017 at 19:57
0
\$\begingroup\$

Here is a slightly optimized version:

# python's default stack size is small
from sys import setrecursionlimit
setrecursionlimit((1<<31)-1)
def ways(n, cache={}):
 if n == 0: return 1
 elif n not in cache:
 cache[n] = sum(ways(s) * ways(n-s-1) for s in xrange(n))
 return cache[n]
answered Jun 15, 2017 at 2:04
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.