Off-by-one on range boundaries
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Break down a hard problem into reliable checkpoints, edge-case handling, and complexity trade-offs.
There is a test that has n types of questions. You are given an integer target and a 0-indexed 2D integer array types where types[i] = [counti, marksi] indicates that there are counti questions of the ith type, and each one of them is worth marksi points.
Return the number of ways you can earn exactly target points in the exam. Since the answer may be too large, return it modulo 109 + 7.
Note that questions of the same type are indistinguishable.
3 questions of the same type, then solving the 1st and 2nd questions is the same as solving the 1st and 3rd questions, or the 2nd and 3rd questions.Example 1:
Input: target = 6, types = [[6,1],[3,2],[2,3]] Output: 7 Explanation: You can earn 6 points in one of the seven ways: - Solve 6 questions of the 0th type: 1 + 1 + 1 + 1 + 1 + 1 = 6 - Solve 4 questions of the 0th type and 1 question of the 1st type: 1 + 1 + 1 + 1 + 2 = 6 - Solve 2 questions of the 0th type and 2 questions of the 1st type: 1 + 1 + 2 + 2 = 6 - Solve 3 questions of the 0th type and 1 question of the 2nd type: 1 + 1 + 1 + 3 = 6 - Solve 1 question of the 0th type, 1 question of the 1st type and 1 question of the 2nd type: 1 + 2 + 3 = 6 - Solve 3 questions of the 1st type: 2 + 2 + 2 = 6 - Solve 2 questions of the 2nd type: 3 + 3 = 6
Example 2:
Input: target = 5, types = [[50,1],[50,2],[50,5]] Output: 4 Explanation: You can earn 5 points in one of the four ways: - Solve 5 questions of the 0th type: 1 + 1 + 1 + 1 + 1 = 5 - Solve 3 questions of the 0th type and 1 question of the 1st type: 1 + 1 + 1 + 2 = 5 - Solve 1 questions of the 0th type and 2 questions of the 1st type: 1 + 2 + 2 = 5 - Solve 1 question of the 2nd type: 5
Example 3:
Input: target = 18, types = [[6,1],[3,2],[2,3]] Output: 1 Explanation: You can only earn 18 points by answering all questions.
Constraints:
1 <= target <= 1000n == types.length1 <= n <= 50types[i].length == 21 <= counti, marksi <= 50Problem summary: There is a test that has n types of questions. You are given an integer target and a 0-indexed 2D integer array types where types[i] = [counti, marksi] indicates that there are counti questions of the ith type, and each one of them is worth marksi points. Return the number of ways you can earn exactly target points in the exam. Since the answer may be too large, return it modulo 109 + 7. Note that questions of the same type are indistinguishable. For example, if there are 3 questions of the same type, then solving the 1st and 2nd questions is the same as solving the 1st and 3rd questions, or the 2nd and 3rd questions.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Array · Dynamic Programming
6 [[6,1],[3,2],[2,3]]
5 [[50,1],[50,2],[50,5]]
18 [[6,1],[3,2],[2,3]]
coin-change-ii)minimum-total-distance-traveled)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #2585: Number of Ways to Earn Points
class Solution {
public int waysToReachTarget(int target, int[][] types) {
int n = types.length;
final int mod = (int) 1e9 + 7;
int[][] f = new int[n + 1][target + 1];
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
int count = types[i - 1][0], marks = types[i - 1][1];
for (int j = 0; j <= target; ++j) {
for (int k = 0; k <= count; ++k) {
if (j >= k * marks) {
f[i][j] = (f[i][j] + f[i - 1][j - k * marks]) % mod;
}
}
}
}
return f[n][target];
}
}
// Accepted solution for LeetCode #2585: Number of Ways to Earn Points
func waysToReachTarget(target int, types [][]int) int {
n := len(types)
f := make([][]int, n+1)
for i := range f {
f[i] = make([]int, target+1)
}
f[0][0] = 1
const mod = 1e9 + 7
for i := 1; i <= n; i++ {
count, marks := types[i-1][0], types[i-1][1]
for j := 0; j <= target; j++ {
for k := 0; k <= count; k++ {
if j >= k*marks {
f[i][j] = (f[i][j] + f[i-1][j-k*marks]) % mod
}
}
}
}
return f[n][target]
}
# Accepted solution for LeetCode #2585: Number of Ways to Earn Points
class Solution:
def waysToReachTarget(self, target: int, types: List[List[int]]) -> int:
n = len(types)
mod = 10**9 + 7
f = [[0] * (target + 1) for _ in range(n + 1)]
f[0][0] = 1
for i in range(1, n + 1):
count, marks = types[i - 1]
for j in range(target + 1):
for k in range(count + 1):
if j >= k * marks:
f[i][j] = (f[i][j] + f[i - 1][j - k * marks]) % mod
return f[n][target]
// Accepted solution for LeetCode #2585: Number of Ways to Earn Points
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #2585: Number of Ways to Earn Points
// class Solution {
// public int waysToReachTarget(int target, int[][] types) {
// int n = types.length;
// final int mod = (int) 1e9 + 7;
// int[][] f = new int[n + 1][target + 1];
// f[0][0] = 1;
// for (int i = 1; i <= n; ++i) {
// int count = types[i - 1][0], marks = types[i - 1][1];
// for (int j = 0; j <= target; ++j) {
// for (int k = 0; k <= count; ++k) {
// if (j >= k * marks) {
// f[i][j] = (f[i][j] + f[i - 1][j - k * marks]) % mod;
// }
// }
// }
// }
// return f[n][target];
// }
// }
// Accepted solution for LeetCode #2585: Number of Ways to Earn Points
function waysToReachTarget(target: number, types: number[][]): number {
const n = types.length;
const mod = 10 ** 9 + 7;
const f: number[][] = Array.from({ length: n + 1 }, () => Array(target + 1).fill(0));
f[0][0] = 1;
for (let i = 1; i <= n; ++i) {
const [count, marks] = types[i - 1];
for (let j = 0; j <= target; ++j) {
for (let k = 0; k <= count; ++k) {
if (j >= k * marks) {
f[i][j] = (f[i][j] + f[i - 1][j - k * marks]) % mod;
}
}
}
}
return f[n][target];
}
Use this to step through a reusable interview workflow for this problem.
Pure recursion explores every possible choice at each step. With two choices per state (take or skip), the decision tree has 2ⁿ leaves. The recursion stack uses O(n) space. Many subproblems are recomputed exponentially many times.
Each cell in the DP table is computed exactly once from previously solved subproblems. The table dimensions determine both time and space. Look for the state variables — each unique combination of state values is one cell. Often a rolling array can reduce space by one dimension.
Review these before coding to avoid predictable interview regressions.
Wrong move: Loop endpoints miss first/last candidate.
Usually fails on: Fails on minimal arrays and exact-boundary answers.
Fix: Re-derive loops from inclusive/exclusive ranges before coding.
Wrong move: An incomplete state merges distinct subproblems and caches incorrect answers.
Usually fails on: Correctness breaks on cases that differ only in hidden state.
Fix: Define state so each unique subproblem maps to one DP cell.