📓 Cabinet of Ideas

20 Patterns to Master Dynamic Programming

20 Patterns to Master Dynamic Programming #

Excerpt #

23 - Dynamic Programming Patterns #


Dynamic Programming (DP) is arguably the most difficult topic for coding interviews.

But, like any other topic, the fastest way to learn it is by understanding different patterns that can help you solve a wide variety of problems.

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e7e3556-d44e-48b4-80f1-787f73294743_7064x4178.png)

In this article, I’ll walk you through 20 patterns that will make learning DP much easier.

I’ll share when to use each pattern and provide links to LeetCode problems you can practice to learn them better.

I have listed them from easy to hard and also linked resources to learn each pattern.

1. Fibonacci Sequence #

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e6c90e0-e1ab-4295-92ae-e84dfa311088_1768x1652.png)

The Fibonacci sequence pattern is useful when the solution to a problem depends on the solutions of smaller instances of the same problem.

There is a clear recursive relationship, often resembling the classic Fibonacci sequence F(n) = F(n-1) + F(n-2).

LeetCode Problems: #

2. Kadane’s Algorithm #

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16ebf522-0166-434d-808f-551672e9bd59_2048x886.png)

Kadane’s Algorithm is primarily used for solving the Maximum Subarray Problem and its variations where the problem asks to optimize a contiguous subarray within a one-dimensional numeric array

LeetCode Problems: #

3. 0/1 Knapsack #

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2202a869-3974-4e9e-8131-b2c2bb581f41_2440x1766.png)

The 0/1 Knapsack pattern is useful when:

  1. You have a set of items, each with a weight and a value.

  2. You need to select a subset of these items.

  3. There’s a constraint on the total weight (or some other resource) you can use.

  4. You want to maximize (or minimize) the total value of the selected items.

  5. Each item can be chosen only once (hence the “0/1” - you either take it or you don’t).

LeetCode Problems: #

4. Unbounded Knapsack #

The Unbounded Knapsack pattern is useful when:

  1. You have a set of items, each with a weight and a value.

  2. You need to select items to maximize total value.

  3. There’s a constraint on the total weight (or some other resource) you can use.

  4. You can select each item multiple times (unlike 0/1 Knapsack where each item can be chosen only once).

  5. The supply of each item is considered infinite.

LeetCode Problems: #

5. Longest Common Subsequence (LCS) #

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffd1dc9bd-6284-4ed5-9ab4-f4578516e2b7_2048x1358.png)

The Longest Common Subsequence pattern is useful when you are given two sequences and need to find a subsequence that appears in the same order in both the given sequences.

LeetCode Problems: #

6. Longest Increasing Subsequence (LIS) #

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6c5abaf-00e2-4649-a592-b0776d1fef72_2048x836.png)

The Longest Increasing Subsequence pattern is used to solve problems that involve finding the longest subsequence of elements in a sequence where the elements are in increasing order.

LeetCode Problems: #

7. Palindromic Subsequence #

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F340048a6-9e4c-447f-8685-465b44c0e586_1756x1905.png)

The Palindromic Subsequence pattern is used when solving problems that involve finding a subsequence within a sequence (usually a string) that reads the same forwards and backwards.

LeetCode Problems: #

8. Edit Distance #

The Edit Distance pattern is used to solve problems that involve transforming one sequence (usually a string) into another sequence using a minimum number of operations.

The allowed operations typically include insertion, deletion, and substitution.

LeetCode Problems: #

9. Subset Sum #

The Subset Sum pattern is used to solve problems where you need to determine whether a subset of elements from a given set can sum up to a specific target value.

LeetCode Problems: #

10. String Partition #

The String Partition pattern is used to solve problems that involve partitioning a string into smaller substrings that satisfy certain conditions.

It’s useful when:

  • You’re working with problems involving strings or sequences.

  • The problem requires splitting the string into substrings or subsequences.

  • You need to optimize some property over these partitions (e.g., minimize cost, maximize value).

  • The solution to the overall problem can be built from solutions to subproblems on smaller substrings.

  • There’s a need to consider different ways of partitioning the string.

LeetCode Problems: #

11. Catalan Numbers #

The Catalan Number pattern is used to solve combinatorial problems that can be decomposed into smaller, similar subproblems.

Some of the use-cases of this pattern include:

  • Counting the number of valid parentheses expressions of a given length

  • Counting the number of distinct binary search trees that can be formed with n nodes.

  • Counting the number of ways to triangulate a polygon with n+2 sides.

LeetCode Problems: #

12. Matrix Chain Multiplication #

This pattern is used to solve problems that involve determining the optimal order of operations to minimize the cost of performing a series of operations.

It is based on the popular optimization problem: Matrix Chain Multiplication.

It’s useful when:

  1. You’re dealing with a sequence of elements that can be combined pairwise.

  2. The cost of combining elements depends on the order of combination.

  3. You need to find the optimal way to combine the elements.

  4. The problem involves minimizing (or maximizing) the cost of operations of combining the elements.

LeetCode Problems: #

13. Count Distinct Ways #

This pattern is useful when:

  1. You need to count the number of different ways to achieve a certain goal or reach a particular state.

  2. The problem involves making a series of choices or steps to reach a target.

  3. There are multiple valid paths or combinations to reach the solution.

  4. The problem can be broken down into smaller subproblems with overlapping solutions.

  5. You’re dealing with combinatorial problems that ask “in how many ways” can something be done.

LeetCode Problems: #

14. DP on Grids #

[

]( https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1678d80-f4fc-4d78-938a-d30f3d0d0343_1832x1726.png)

The DP on Grids pattern is used to solve problems that involve navigating or optimizing paths within a grid (2D array).

For these problems, you need to consider multiple directions of movement (e.g., right, down, diagonal) and solution at each cell depends on the solutions of neighboring cells.

LeetCode Problems: #

15. DP on Trees #

The DP on Trees pattern is useful when:

  1. You’re working with tree-structured data represented by nodes and edges.

  2. The problem can be broken down into solutions of subproblems that are themselves tree problems.

  3. The problem requires making decisions at each node that affect its children or parent.

  4. You need to compute values for nodes based on their children or ancestors.

LeetCode Problems: #

16. DP on Graphs #

The DP on Graphs pattern is useful when:

  1. You’re dealing with problems involving graph structures.

  2. The problem requires finding optimal paths, longest paths, cycles, or other optimized properties on graphs.

  3. You need to compute values for nodes or edges based on their neighbors or connected components.

  4. The problem involves traversing a graph while maintaining some state.

LeetCode Problems: #

17. Digit DP #

The Digit DP Pattern is useful when:

  1. You’re dealing with problems involving counting or summing over a range of numbers.

  2. The problem requires considering the digits of numbers individually.

  3. You need to find patterns or properties related to the digits of numbers within a range.

  4. The range of numbers is large (often up to 10^18 or more), making brute force approaches infeasible.

  5. The problem involves constraints on the digits.

LeetCode Problems: #

18. Bitmasking DP #

The Bitmasking DP pattern is used to solve problems that involve a large number of states or combinations, where each state can be efficiently represented using bits in an integer.

It’s particularly useful when:

  1. You’re dealing with problems involving subsets or combinations of elements.

  2. The total number of elements is relatively small (typically <= 20-30).

  3. You need to efficiently represent and manipulate sets of elements.

  4. The problem involves making decisions for each element (include/exclude) or tracking visited/unvisited states.

  5. You want to optimize space usage in DP solutions.

LeetCode Problems: #

19. Probability DP #

This pattern is useful when:

  1. You’re dealing with problems involving probability calculations.

  2. The probability of a state depends on the probabilities of previous states.

  3. You need to calculate the expected value of an outcome.

  4. The problem involves random processes or games of chance.

LeetCode Problems: #

20. State Machine DP #

The State Machine DP Pattern is useful when when:

  1. The problem can be modeled as a series of states and transitions between these states.

  2. There are clear rules for moving from one state to another.

  3. The optimal solution depends on making the best sequence of state transitions.

  4. The problem involves making decisions that affect future states.

  5. There’s a finite number of possible states, and each state can be clearly defined.

LeetCode Problems: #

Thank you so much for reading.

If you found it valuable, hit a like ❤️ and consider subscribing for more such content every week.

If you have any questions or suggestions, leave a comment.

This post is public so feel free to share it.

Share

Checkout my Youtube channel for more in-depth content.

Follow me on LinkedIn and X to stay updated.

Checkout my GitHub repositories for free interview preparation resources.

I hope you have a lovely day!

See you soon,

Ashish