Chapter 8 - Recursion and Dynamic Programming

One-stop information center for your next technical interview


Chapter 8 - Recursion and Dynamic Programming

When talking about recursion algorithm, always remember to include the recursion stack when considering the space complexity. Also, it may be possible to convert a recursive algorithm to an iterative one using stack (to emulate the stack trace). DP & memoization is basically using an array to cache the result of some recursive calls.

Examples

8.1 Triple Step

steps(n) = steps(n - 1) + steps(n - 2) + steps(n - 3)

8.2 Robot in a Grid

A certain cell is defined to be reachable if either its left or up cell is reachable. At the beginning, only the top-left cell is reachable. Just iterate over this 2D array.

8.3 Magic Index

To find the index such that A[i] = i, we have to use a modified version of binary search. If A[n / 2] < n / 2, we go to the right half; otherwise, we go to the left half.

If the values are not distinct, we need to modify the algorithm above a bit. If A[n / 2] < n / 2, we not only need to search the right half, we have to search for part of the left half, specifically, in the range of [A[n / 2], n / 2].

8.4 Power Set

There are 2^n subsets for a set with n elements. Use a recursion algorithm, by having each element either present or absent. Alternatively, use a bitmap to implement an iterative approach (i.e., integers from 0 to 2^n - 1).

8.5 Recursive Multiply

In fact, you should think about how CPU instruction set would perform multiplication. We convert two operands to their binary format. We then multiply bit-by-bit (add, left shift, repeat). Of course, you can do things like a * b = (a / 2) * (b * 2) from an SE perspective. But that is not really necessary and it is probably not performant as well.

8.6 Tower of Hanoi

This is a very classical recursion problem. We can understand it using mathematical reduction.

8.7 Permutations without Dups

This one is also classical. Use Perm(n - 1) to compute Perm(n).

8.8 Permutations with Dups

We represent the input as a hashtable from character to the number of occurrences. Then follow the same approach.

8.9 Parens

Use a recursive solution. Parens(a, b) = Parens(a - 1, b) + Parens(a, b - 1), where a and b represent the number of open & close brackets respectively.

8.10 Paint Fill

To be honest, this problem is not clear at all. Most candidates may not be sure what it means at all. But it turns out that it should be either an DFS or BFS on the given 2D array.

8.11 Coins

Coins(n) = Coins(n - 5) + Coins(n - 10) + Coins(n - 25)

8.12 Eight Queens

Use recursion. Consider the queens one by one.

8.13 Stack of Boxes

Boxes(Integer.MaxValue, Integer.MaxValue) = Math.Max( Boxes(w1, d1) + h1, Boxes(w2, d2) + h2, …, Boxes(wn, dn) + hn, )

8.14 Boolean Evaluation

We just need to find a place to split the whole expression into two parts and then apply AND or OR to them. XOR could be applied to either operand. Certainly, we could use short-circuit evaluation for optimization.