This problem is very similar to Fibonacci and you can create an iterative solutions that is much more performant than the recursive solution. I modified the recursive function a little bit because from reading the question I interpret n = 0 as having 0 ways to empty the box by removing 1 or 3 items. Here is the modified recursive function.
def numberOfWays(n):
if n <= 0:
return 0
elif n in (2, 1):
return 1
elif n == 3:
return 2
else:
return numberOfWays(n - 3) + numberOfWays(n - 1)
Here is an iterative solution that will use less memory than the one Michael provided since it only stores 3 numbers instead of every single number in the series up to n:
def numberOfWays(n):
if n == 0:
return 0
elif n <= 2:
return 1
elif n == 3:
return 2
a, b, c, = 1, 1, 2
for i in range(n-3):
a, b, c, = b, c, c + a
return c
I counted the number of loop iterations for the iterative function and the number of function calls for the recursive one to show how much better it performs.
Iterative
n of 10 = 28 | Loop Iterations: 7
n of 9 = 19 | Loop Iterations: 6
n of 8 = 13 | Loop Iterations: 5
n of 7 = 9 | Loop Iterations: 4
n of 6 = 6 | Loop Iterations: 3
n of 5 = 4 | Loop Iterations: 2
n of 4 = 3 | Loop Iterations: 1
n of 3 = 2 | Loop Iterations: 0
n of 2 = 1 | Loop Iterations: 0
n of 1 = 1 | Loop Iterations: 0
n of 0 = 0 | Loop Iterations: 0
Recursive:
n of 10 = 28 | Function calls: 37
n of 9 = 19 | Function calls: 25
n of 8 = 13 | Function calls: 17
n of 7 = 9 | Function calls: 11
n of 6 = 6 | Function calls: 7
n of 5 = 4 | Function calls: 5
n of 4 = 3 | Function calls: 3
n of 3 = 2 | Function calls: 1
n of 2 = 1 | Function calls: 1
n of 1 = 1 | Function calls: 1
n of 0 = 0 | Function calls: 1
Caching/Memoizing the result would be good if this function were used in software where it will be called many times with the same parameters regardless of the underlying implementation. However this probably won't help you pass all the automated tests in an online coding challenge.