
This course includes our updated coding exercises so you can practice your skills as you learn.
See a demo
Explore self-similarity and fractals like the Sierpinski triangle, and learn recursive algorithms that solve problems from coin change to grid paths, tree structures, and chess, culminating in dynamic programming optimization.
Explore recursion through a simple print cat function that calls itself. Learn the three main parts: parameters, base case, and recurrence relation that prevent infinite recursion.
Explore the Fibonacci sequence as a first recursive algorithm, including recurrence, base cases, and how recursion forms a call tree, with a preview of dynamic programming to optimize.
Map all valid ways to divide colored blocks into groups with no duplicates using decision trees. See how recursion creates a variable-depth tree and leads to dynamic programming insights.
Learn to calculate the worst-case space and time complexity of recursive algorithms using max depth, max branching factor, and the call stack, plus formulas O(B^D * t) and O(d * S).
Explore two main types of recursive algorithms, including self-similar and divide algorithms, and build a solid algorithm foundation before tackling dynamic programming.
Explore self-similar algorithms using recursion, defining a recurrence such as f(n)=f(n-1)+n, establishing base cases, and applying to Gauss summation to sum 1 to n.
Derive the depth of a binary tree using self-similar tree algorithms. Apply a recurrence that maxes the depths of the left and right subtrees and adds one for the root.
Explore self-similar thief algorithms that solve the max path sum in a binary tree by borrowing solutions from a related problem via max branch sums and a wrapper function.
Explore backtracking algorithms that prune decision sequences early, using the N-queens example to show tracking attackable columns and diagonals with sets and recursion.
Explore summation algorithms that enumerate all permutations of adding coins to reach a target value using a decision tree with a base case and recurrence.
Learn to transform permutation coin change into a combination problem using a recurrence and a two-path decision tree that groups coins by type via a current coin index.
Discover how dynamic programming speeds up recursive algorithms by avoiding duplicate work, illustrated by Fibonacci, and apply it to the lazy house robber with at most k non-adjacent houses.
Builds a decision tree algorithm for the lazy house robber problem, tracking index and current robbed, and compares rob versus skip decisions under end-of-list and k-house limits.
Explore a self-similar recursive approach to the lazy house robber problem, modeling with f(houses, k) and using a two-way choice to maximize money under non-adjacent and cap k constraints.
Master dynamic programming by caching answers to subproblems with memoization in a memoization table, reducing overlapping computations in recursive and decision-tree approaches, using keys like index and k.
discover how bottom-up tabulation unifies recursive algorithms with dynamic programming by replacing recursion with for loops, leveraging memoization, and reducing space and overhead.
Compute dynamic programming complexity with memoization or tabulation by multiplying subproblems by time per subproblem, with the lazy house robber as an example, explaining the time-space trade-off.
Examine how tabulation lowers space complexity in dynamic programming by using rolling arrays and two-row optimization for problems like Fibonacci and lazy house robber.
Apply recursion and dynamic programming principles to real problems using memoization or tabulation, recognizing when overlapping subproblems exist and when DP isn’t suitable, as in N-queens.
When I was preparing for coding interviews a while back, I found recursion and dynamic programming to be among the hardest topics covered. It felt like it took me weeks to get good at solving these types of problems. After I finished preparing for interviews, I thought there must be an easier way for someone to learn how to solve these types of problems, so they can learn this much quicker. After solving more than 100 recursive and dynamic programming problems, I created a problem-solving framework that you can use to solve these types of problems.
This course teaches you this framework by first splitting up all recursive algorithms into two types: self-similar algorithms and decision tree algorithms. Self-similar algorithms solve problems where there is an easy to see self-similar relationship with the problem itself we are solving for, and decision tree algorithms solve problems by 'trying' every possible decision sequence in a system. We will spend time building a strong foundation on how to solve problems with recursion (even problems that are typically referred to as dynamic programming problems), and then, with a strong foundation, we will learn how to improve our recursive algorithms with dynamic programming.
Prerequisites:
The course uses Python, requiring only a basic understanding of the language.
A basic understanding of non-recursive space and time complexity.
A basic understanding of non-recursive data structures and algorithms, such as hash tables and tree structures, is required.