Each section contains:
- Pattern Name
- Problem Examples
- Key Decisions
- Reusable Recursion/DP Template
1๏ธโฃ Take / Not Take Pattern
Base of all subset/knapsack-style problems.
๐น Problem Types:
- 0/1 Knapsack
- Subset Sum / Count Subsets with Sum
- Target Sum
- Partition Equal Subset
- House Robber
๐น Template:
int solve(int i, int[] nums, int sum) {
if (i == nums.length) return base_case;
// Not take
int notTake = solve(i + 1, nums, sum);
// Take if valid
int take = 0;
if (nums[i] <= sum)
take = solve(i + 1, nums, sum - nums[i]);
return Math.max(take, notTake); // or count, min, etc.
}
2๏ธโฃ Unbounded Take / Not Take
Use when elements can be picked multiple times.
๐น Problem Types:
- Unbounded Knapsack
- Coin Change (Min coins or Total Ways)
- Rod Cutting
๐น Template:
int solve(int i, int[] nums, int target) {
if (i == nums.length) return base_case;
// Take: stay on same i
int take = Integer.MAX_VALUE;
if (nums[i] <= target)
take = 1 + solve(i, nums, target - nums[i]);
// Not take: move to next i
int notTake = solve(i + 1, nums, target);
return Math.min(take, notTake);
}
3๏ธโฃ DP on Subsequences
LCS, LIS, Edit Distance โ comparing sequences.
๐น Problem Types:
- Longest Common Subsequence
- Edit Distance
- Longest Palindromic Subsequence
- Minimum Insertions/Deletions
๐น Template:
int solve(int i, int j, String s1, String s2) {
if (i == s1.length() || j == s2.length()) return base_case;
if (s1.charAt(i) == s2.charAt(j))
return 1 + solve(i + 1, j + 1, s1, s2);
return Math.max(
solve(i + 1, j, s1, s2),
solve(i, j + 1, s1, s2)
);
}
4๏ธโฃ DP on Index and State
Track more than just index โ also a "state" (like previous selection, count, etc.)
๐น Problem Types:
- Longest Increasing Subsequence
- Paint House / Job Scheduling
- Maximum Sum of Non-Adjacent Elements
๐น Template:
int solve(int i, int prevIndex, int[] nums) {
if (i == nums.length) return 0;
// Not take
int notTake = solve(i + 1, prevIndex, nums);
// Take
int take = 0;
if (prevIndex == -1 || nums[i] > nums[prevIndex])
take = 1 + solve(i + 1, i, nums);
return Math.max(take, notTake);
}
5๏ธโฃ Partition DP
Split array into segments (e.g., Palindrome Partition, Burst Balloons).
๐น Problem Types:
- Palindrome Partitioning II
- Matrix Chain Multiplication
- Burst Balloons
๐น Template:
int solve(int i, int j, int[] arr) {
if (i >= j) return 0;
int minCost = Integer.MAX_VALUE;
for (int k = i; k < j; k++) {
int cost = solve(i, k, arr) + solve(k + 1, j, arr) + costFunction(i, k, j);
minCost = Math.min(minCost, cost);
}
return minCost;
}
6๏ธโฃ Decision Tree / Backtracking
Explore all paths โ often exponential, but needed for enumeration problems.
๐น Problem Types:
- Generate Subsequences
- Combinations / Permutations
- N-Queens
- Word Search
๐น Template:
void backtrack(int i, List<Integer> path, int[] nums) {
if (i == nums.length) {
result.add(new ArrayList<>(path));
return;
}
// Take
path.add(nums[i]);
backtrack(i + 1, path, nums);
path.remove(path.size() - 1);
// Not take
backtrack(i + 1, path, nums);
}
7๏ธโฃ Grid DP
Grid traversal problems with movement in directions.
๐น Problem Types:
- Unique Paths / Obstacles
- Minimum Path Sum
- Grid Cost Problems
๐น Template:
int solve(int i, int j, int[][] grid) {
if (i >= m || j >= n) return INF;
if (i == m - 1 && j == n - 1) return grid[i][j];
return grid[i][j] + Math.min(
solve(i + 1, j, grid),
solve(i, j + 1, grid)
);
}
8๏ธโฃ Digit DP
Special type of DP on digits of a number with constraints (e.g., "count numbers with X property").
๐น Problem Types:
- Count Numbers <= N with some digit rules
- Sum of Digits in range
- Bounded digit DP
๐น Template:
int solve(int pos, boolean tight, boolean leadingZero, String num) {
if (pos == num.length()) return base_case;
int limit = tight ? num.charAt(pos) - '0' : 9;
int res = 0;
for (int d = 0; d <= limit; d++) {
res += solve(pos + 1,
tight && (d == limit),
leadingZero && (d == 0),
num);
}
return res;
}
9๏ธโฃ Bitmask DP
Useful when tracking subset combinations efficiently with bitmasking.
๐น Problem Types:
- Traveling Salesman Problem (TSP)
- Assignment Problems
- Max Score Assignments
๐น Template:
int solve(int mask, int pos, int[][] cost) {
if (mask == allVisitedMask) return 0;
if (dp[mask][pos] != -1) return dp[mask][pos];
int ans = Integer.MAX_VALUE;
for (int city = 0; city < n; city++) {
if ((mask & (1 << city)) == 0) {
ans = Math.min(ans, cost[pos][city] + solve(mask | (1 << city), city, cost));
}
}
return dp[mask][pos] = ans;
}
๐ Memoization and Tabulation Conversions
- Memoization โ Top-down recursion with
dp[]
array or map. - Tabulation โ Bottom-up DP using
dp[]
arrays with for-loops. - Space Optimization โ Compress 2D
dp[i][j]
into 1Dprev[]
andcurr[]
if dependencies allow.
๐ฆ Final Tips
Pattern | Look For |
---|---|
Take / Not Take | Subset, inclusion-exclusion |
Unbounded | Reuse of elements allowed |
Subsequences | Comparing two sequences |
Partition DP | Problem splits at a point |
Backtracking | Enumerate all combinations |
Grid DP | Movement in a matrix |
Bitmask DP | State of "used/not used" |
Digit DP | Number digit constraints |
Game DP | Two players, optimal strategy |
Top comments (0)