Skip to content

Approaches

Bottom-Up Approach

Solve for a simple case (such as a list with one element) and work your way up.

Top-Down Approach

How can we divide the problem for case N into subproblems

Half and Half Approach

Solve data by splitting into half.

Recursive vs Iterative

Recursive can be very space inefficient. It is better to implement a recursive algorithm iteratively. All recursive algorithms can be implemented iteratively.

How to do this?

int fib(int i) {
  if (i == 0) return 0;
  if (i == 1) return 1;
  return fib(i - 1) + fib(i - 2);
}
int fib(int i) {

  if (i == 0) return 0;
  if (i == 1) return 1;

  int acc = 0;

  while (true) {

  }
}

Dynamic Programming and Memoization

Essentially is a recursive program where subproblems are repeated, so we cache these problems.

Memoization is top-down dynamic programming. Others refer DP as bottom up.

Fibonacci Numbers

Recursive

int fib(int i) {
  if (i == 0) return 0;
  if (i == 1) return 1;
  return fib(i - 1) + fib(i - 2);
}

Runtime? O( 2^n^ ). Every n makes two calls.

Memoization

int fib(int i) {
  return fib(i, new int[i + 1])
}

if fib(int i, int[] memo) {
  if (i == 0 || i == 1) return i;

  if (memo[i] == 0) {
    memo[i] = fib(i - 1, memo) + fib(i - 2, memo);
  }

  return memo[i];
}

Runtime? O( n ). Every n is calculated once

Bottoms Up DP

if fib(int i) {
  if (i == 0 || i == 1) return i;

  int[] memo = new int[n];
  memo[0] = 0;
  memo[1] = 1;

  for(int j = 2; j < n; j++) {
    memo[j] = memo[j - 1] + memo[j - 2];
  }

  return memo[n - 1] + memo[n - 2];
}

Can this be done with recursion? No. Because recursion is about breaking a problem down. This is building it up.