Recursion

A recursion has 2 key points.

  • end condition

  • recursion formula

End condition is the edge case.

Recursion formula presents the way of spliting the problem into several sub problems.

For example, climbing stairs.

The edge cases are

  • one staire
  • two staires

The problem can be split to sum up the ways of climbing n - 1 staires and n - 2 staires.

So, the solution is simple.

def climb_staires(n: int) -> int:
    if n == 1: return 1
    if n == 2: return 2
    return climb_staires(n - 2) + climb_staires(n - 1)

What's more, we can use Dynamic Programming. It avoids stack overflow and repeated calculation.

def climb_staires(n: int) -> int:
    dp = list(range(0, n+1)) # end condition: dp[1] = 1; dp[2] = 2
    
    if n > 2:
        for i in range(3, n+1):
            dp[i] = dp[i - 2] + dp[i - 1] # recursion formula
    
    return dp[n]

Stack overflow

A common problem of recursion is the stack overflow.

We will create a space once a function is called. Then, we push this space into a stack. If the recursion is too deep, stack overflow happens.

Repeated calculation

Somtimes, the same result can be calculated repeatedly.

For example, in climbing staires, we set n == 4:

- f(4)
  |-f(2)
  |-f(3)
    |-f(2)
    |-f(1)

f(2) is called 2 times.

We need to create a data structure to cache the internal results. Dynamic Programming uses an array.

Besides, we can use hash map.

def climb_staires(n):
    hash_map = {}
    hash_map[1] = 1
    hash_map[2] = 2

    if n in hash_map:
        return hash_map[n]
    
    hash_map[n] = climb_staires(n - 2) + climb_staires(n - 1) 
    return hash_map[n]