Jump into concepts and practice - no test required
or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
📋
Problem
Imagine you are a freelancer with multiple job offers, each with a start time, end time, and profit. You want to schedule jobs to maximize your total earnings without overlapping any jobs.
Given n jobs where every job is represented as (startTime, endTime, profit), find the maximum profit you can earn by scheduling non-overlapping jobs. You may choose to skip some jobs. Return the maximum profit achievable.
Edge cases: All jobs overlap completely → output is max single job profitJobs with same start and end times but different profits → pick highest profit jobJobs sorted in descending order of end time → algorithm must still work
def jobScheduling(startTime, endTime, profit):
# Write your solution here
pass
class Solution {
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
// Write your solution here
return 0;
}
}
#include <vector>
using namespace std;
int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {
// Write your solution here
return 0;
}
function jobScheduling(startTime, endTime, profit) {
// Write your solution here
}
Coming soon
0/9
Common Bugs to Avoid
Wrong: Less than max profit due to greedy scheduling by earliest end timeUsing greedy approach instead of DP with binary search for last non-conflicting job✅ Implement DP recurrence dp[i] = max(dp[i-1], profit[i] + dp[last_non_conflict]) with binary search to find last non-conflicting job
Wrong: Sum of all profits ignoring overlapsNot enforcing non-overlapping constraint in DP or binary search✅ Ensure binary search finds last job that ends before current job starts and add dp[last_non_conflict] only if no overlap
Wrong: Incorrect result due to unsorted jobsNot sorting jobs by end time before DP and binary search✅ Sort jobs by end time before processing and binary searching
Wrong: Crash or wrong output on empty inputNo base case handling for empty input arrays✅ Add base case: if no jobs, return 0 immediately
Wrong: Wrong profit for single job inputDP initialization incorrect for single element✅ Initialize dp[0] = profit[0] for single job input
✓
Test Cases
Focus on handling base cases like empty input and single job scenarios.
Beware of greedy traps and ensure correct sorting and binary search usage.
Optimize your DP solution to O(n log n) to handle large inputs efficiently.
Schedule jobs 1 (1-3, profit 20), 4 (4-6, profit 70), and 5 (6-9, profit 60) for total 150.
💡 Sort jobs by their end times to consider scheduling order.
💡 Use binary search to find the last non-conflicting job for each job.
💡 Use DP to store max profit up to each job: dp[i] = max(dp[i-1], profit[i] + dp[last_non_conflict]).
Why it failed: Incorrect output means DP recurrence or binary search for last non-conflicting job is wrong. Fix by ensuring dp[i] = max(dp[i-1], profit[i] + dp[last_non_conflict]) with correct binary search.
✓ Correctly computes max profit using DP with binary search for non-overlapping jobs.
Why it failed: If output is less than 150, likely binary search or DP state update is incorrect. Fix by verifying binary search returns correct last non-conflicting job index.
✓ DP correctly accounts for overlapping jobs and maximizes profit.
t2_01edge
Input{"startTime":[],"endTime":[],"profit":[]}
Expected0
⏱ Performance - must finish in 2000ms
Empty input means no jobs to schedule, so max profit is 0.
💡 Consider the base case when no jobs are given.
💡 DP array should handle empty input gracefully.
💡 Return 0 immediately if input arrays are empty.
Why it failed: Function crashes or returns non-zero on empty input. Fix by adding base case: if no jobs, return 0.
Greedy approach picking jobs by earliest end time fails; correct is jobs 1 and 4 for total 90 or jobs 3 alone for 100, but best is jobs 1 and 4 for 90 or job 3 alone 100; actually jobs 1 and 4 overlap? Jobs 1(1-3), 4(4-6) no overlap, total 90; job 3 alone 100; best is 100.
💡 Greedy by earliest end time may not yield max profit.
💡 Use DP with binary search to consider all combinations.
💡 Check dp recurrence to avoid greedy trap.
Why it failed: Output less than 100 means greedy approach used. Fix by implementing DP with binary search for last non-conflicting job.
✓ DP correctly avoids greedy trap and finds max profit.
Jobs unsorted by end time; algorithm must sort and still find max profit 150 by scheduling jobs 2,4,5.
💡 Sort jobs by end time before DP.
💡 Binary search depends on sorted end times.
💡 DP recurrence uses sorted jobs to find max profit.
Why it failed: Incorrect output means jobs not sorted by end time before DP. Fix by sorting jobs by end time before processing.
✓ Correctly sorts jobs and computes max profit.
t4_01performance
Input{"_description":"n=100000 at constraint boundary - executor generates this input"}
Expectednull
⏱ Performance - must finish in 2000ms
Test with 100000 jobs to verify O(n log n) DP with binary search completes within 2 seconds.
💡 Brute force O(2^n) will time out here.
💡 Use sorting and binary search to achieve O(n log n) complexity.
💡 Optimize DP with binary search for last non-conflicting job.
Why it failed: TLE indicates brute force or inefficient DP used. Fix by implementing O(n log n) DP with binary search.
✓ Algorithm runs within time limit using O(n log n) DP approach.
Practice
(1/5)
1. Consider the following Python code for counting the number of ways to make change. What is the output when calling change(5, [1, 2, 5])?
easy
A. 5
B. 3
C. 4
D. 6
Solution
Step 1: Initialize dp array
dp = [1,0,0,0,0,0] since dp[0]=1.
Step 2: Update dp for each coin
For coin=1: dp becomes [1,1,1,1,1,1]; for coin=2: dp updates to [1,1,2,2,3,3]; for coin=5: dp updates to [1,1,2,2,3,4].
Final Answer:
Option C -> Option C
Quick Check:
dp[5] = 4 matches known output [OK]
Hint: Trace dp updates coin by coin [OK]
Common Mistakes:
Off-by-one in dp indexing
Confusing permutations with combinations
2. You need to find the minimum number of coins required to make up a given amount from an unlimited supply of given coin denominations. Which algorithmic approach guarantees an optimal solution for this problem?
easy
A. Greedy algorithm that picks the largest coin first until the amount is reached
B. Dynamic programming using a 1D array to store minimum coins needed for all amounts up to the target
C. Pure brute force recursion trying all combinations without memoization
D. Sorting coins and using binary search to find the best coin for each sub-amount
Solution
Step 1: Understand problem constraints
The problem requires minimum coins for any amount with unlimited coin usage, which fits unbounded knapsack pattern.
Step 2: Identify algorithm that guarantees optimality
Greedy fails for some coin sets; brute force is correct but inefficient; DP with 1D array efficiently computes minimum coins for all sub-amounts ensuring optimality.
3. Consider the following code snippet implementing the minimum cost for tickets problem. What is the value of dp[0] after the loop completes for the input days = [1,4,6] and costs = [2,7,15]?
4. The following code attempts to solve the Partition to K Equal Sum Subsets problem using DP with bitmask tabulation. Identify the line containing the subtle bug that can cause incorrect results or infinite loops.
def canPartitionKSubsets(nums, k):
total = sum(nums)
if total % k != 0:
return False
target = total // k
n = len(nums)
nums.sort()
if nums[-1] > target:
return False
dp = [-1] * (1 << n)
dp[0] = 0
for mask in range(1 << n):
if dp[mask] == -1:
continue
for i in range(n):
if (mask & (1 << i)) == 0 and dp[mask] + nums[i] <= target:
next_mask = mask | (1 << i)
dp[next_mask] = (dp[mask] + nums[i]) % target
return dp[(1 << n) - 1] == 0
medium
A. Line: dp = [-1] * (1 << n)
B. Line: if dp[next_mask] == -1: (missing in this code)
C. Line: nums.sort()
D. Line: dp[next_mask] = (dp[mask] + nums[i]) % target
Solution
Step 1: Identify missing condition
The code lacks a check if dp[next_mask] is already set, so it overwrites states, causing incorrect results.
Step 2: Pinpoint the buggy line
The line assigning dp[next_mask] unconditionally overwrites previous valid states, breaking memoization.
Final Answer:
Option D -> Option D
Quick Check:
Adding "if dp[next_mask] == -1:" before assignment fixes bug [OK]
Hint: Always check if dp state is unset before assignment [OK]
Common Mistakes:
Overwriting dp states without checking leads to incorrect answers
Not pruning symmetric states increases runtime
5. Suppose now you want to count the number of ways to make change but coins can be used at most once each (no reuse). Which modification to the DP approach correctly solves this variant?
hard
A. Use 1D DP iterating amounts forwards but reset dp array after each coin
B. Use 2D DP with dp[i][w] representing ways using first i coins for amount w, iterating amounts forwards
C. Use the same 1D DP but iterate amounts backwards from amount down to coin value
D. Use greedy approach picking largest coins first until amount is reached
Solution
Step 1: Understand no reuse constraint
Each coin can be used once, so combinations must not count repeated usage of the same coin.
Step 2: Modify DP iteration order
Iterating amounts backwards in 1D DP ensures each coin contributes only once per amount, preventing reuse.
Step 3: Confirm correctness
This approach correctly counts combinations without reuse, unlike forward iteration which allows multiple usage.
Final Answer:
Option C -> Option C
Quick Check:
Backward iteration in 1D DP enforces single usage per coin [OK]
Hint: Backward iteration prevents coin reuse in 1D DP [OK]