At the beginning when we want to recursively solve a problem on LeetCode, what do you come up in your mind? It is terminologies like Divide and Conquer ∪ Dynamic Programming ∪ Backtracking(searching with BFS or DFS).

Divide and conquer partitions the problems into disjoint subproblems and solves the problems recursively, and then combine the solutions to solve the original problem. Dynamic programming is an optimized Divide and conquer, which solves each sub-problem only once and save its answer in a table. There is no recursion. The key in dynamic programming is memoization. Dynamic programming applies when the subproblems overlap — that is, when subproblems share subproblems.

For me, it is a lot easier to use two recursion functions to show the difference of each other.

However, Backtracking searching which usually we see problems in the form of combination and permutation, it is just a way to enumerate all the solutions that is within the constraint condition.

Note: It is very important to differentiate these two subcategories, lessons learned from one Facebook interview.

Normal steps:

  1. Draw examples, then we use a recursion-tree to “divide” the problems into subproblems.2. Solve the “base Case”, whose size usually is 1.3. Merge the results from the subproblems.4. Observe for possible optimization, repeated subprolems we can use “memorization”4. Use coding language to streamline the process5. check more edge cases, and the indexes, e.g. low, high, mid6. Analyze the time and space complexity

Warning: Divide and Conquer can be used to solve the problems. However, it cant get to Best Conveivable Runtime (BCR). For array it is O(n). Therefore, when we brain storming to find better solution, think about other algorithms. For array/string: Sliding window, two pointers with O(n).

For dynamic programming, it is very important to come up with the recursion function. Commonly we have:

Two approaches :

Normally: 1. base cases() and special cases 2. update function, 3. goal, what is the return. And it is harder to write compared with top-down recursive solutions

Note: recursive algorithms can be very space inefficient. Each recursive call adds a new layer to the stack, which means that if your algorithm recurses to a depth of n, it uses at least O(n) memory.

For this reason, it’s often better to implement a recursive algorithm iteratively. All recursive algorithms can be implemented iteratively, although sometimes the code to do so is much more complex. Before diving into the recursive code, ask yourself how hard it would be to implement it iteratively, and discuss the tradeoffs with your interviewers.