LeetCode Problem Workspace
Maximum Profit in Job Scheduling
Compute the maximum profit from non-overlapping jobs using state transition dynamic programming with sorted arrays and binary search.
4
Topics
6
Code langs
3
Related
Practice Focus
Hard · State transition dynamic programming
Answer-first summary
Compute the maximum profit from non-overlapping jobs using state transition dynamic programming with sorted arrays and binary search.
Ace coding interviews with Interview AiBoxInterview AiBox guidance for State transition dynamic programming
Start by sorting jobs based on their end times to enable efficient non-overlapping checks. Use a dynamic programming array to store the maximum profit achievable up to each job. For each job, perform a binary search to find the latest compatible job that ends before the current job starts, then update the DP state with the maximum of including or skipping the current job. This state transition DP approach ensures optimal selection of jobs without overlaps.
Problem Statement
You are given three arrays startTime, endTime, and profit, each of length n, representing n jobs. Job i starts at startTime[i], ends at endTime[i], and yields a profit of profit[i]. Your task is to select a subset of jobs to maximize total profit such that no two selected jobs overlap in time. If a job ends at time X, another job starting at X can be included.
Return the maximum total profit obtainable under these constraints. Optimize your approach using state transition dynamic programming, considering that naive iteration over all subsets is too slow for large n.
Examples
Example 1
Input: startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]
Output: 120
The subset chosen is the first and fourth job. Time range [1-3]+[3-6] , we get profit of 120 = 50 + 70.
Example 2
Input: startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60]
Output: 150
The subset chosen is the first, fourth and fifth job. Profit obtained 150 = 20 + 70 + 60.
Example 3
Input: startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
Output: 6
Example details omitted.
Constraints
- 1 <= startTime.length == endTime.length == profit.length <= 5 * 104
- 1 <= startTime[i] < endTime[i] <= 109
- 1 <= profit[i] <= 104
Solution Approach
Sort Jobs by End Time
First, combine the startTime, endTime, and profit arrays into a list of job tuples. Sort this list by endTime to allow efficient lookups of the last non-overlapping job for each job using binary search.
Dynamic Programming State Transition
Initialize a DP array where dp[i] represents the maximum profit including jobs up to index i. For each job, perform a binary search to find the latest job that ends before the current job starts. Update dp[i] as the maximum of dp[i-1] (skipping current job) and dp[lastCompatible] + profit[i] (including current job).
Binary Search for Compatible Jobs
Use binary search to efficiently locate the last job that finishes before the current job starts. This avoids linear scans and maintains the overall time complexity near O(n log n). Each DP update then considers only valid non-overlapping sequences.
Complexity Analysis
| Metric | Value |
|---|---|
| Time | Depends on the final approach |
| Space | Depends on the final approach |
Time complexity is O(n log n) due to sorting and binary search for each job. Space complexity is O(n) for storing DP states and the combined job list.
What Interviewers Usually Probe
- Expect sorting by end times before DP.
- Look for correct DP state definition to store maximum profit up to each job.
- Binary search for previous compatible job is crucial for efficiency.
Common Pitfalls or Variants
Common pitfalls
- Forgetting that a job ending at X can allow a new job starting at X.
- Performing linear search instead of binary search, increasing runtime.
- Incorrectly updating DP array, not considering the maximum between including or skipping a job.
Follow-up variants
- Allow jobs with equal start and end times and handle them in DP updates.
- Find the maximum number of jobs instead of profit using a similar DP approach.
- Add a constraint on maximum total duration and adapt the DP to track both profit and duration.
FAQ
What is the main approach to solve Maximum Profit in Job Scheduling?
Use state transition dynamic programming with jobs sorted by end time and binary search to find the latest non-overlapping job for each step.
Can jobs that end and start at the same time be scheduled together?
Yes, a job ending at time X allows inclusion of another job starting at X without overlapping.
What is the time complexity for this DP with binary search approach?
Sorting takes O(n log n) and each job uses O(log n) binary search, resulting in O(n log n) overall time complexity.
How does GhostInterview help with edge cases?
It guides users to check DP updates for overlapping jobs and ensures correct maximum profit calculations on examples.
Are there common mistakes to avoid in this problem?
Yes, forgetting inclusive end-start scheduling, not using binary search, or miscalculating DP states are frequent errors.
Solution
Solution 1: Memoization Search + Binary Search
First, we sort the jobs by start time in ascending order, then design a function $dfs(i)$ to represent the maximum profit that can be obtained starting from the $i$-th job. The answer is $dfs(0)$.
class Solution:
def jobScheduling(
self, startTime: List[int], endTime: List[int], profit: List[int]
) -> int:
@cache
def dfs(i):
if i >= n:
return 0
_, e, p = jobs[i]
j = bisect_left(jobs, e, lo=i + 1, key=lambda x: x[0])
return max(dfs(i + 1), p + dfs(j))
jobs = sorted(zip(startTime, endTime, profit))
n = len(profit)
return dfs(0)Solution 2: Dynamic Programming + Binary Search
We can also change the memoization search in Solution 1 to dynamic programming.
class Solution:
def jobScheduling(
self, startTime: List[int], endTime: List[int], profit: List[int]
) -> int:
@cache
def dfs(i):
if i >= n:
return 0
_, e, p = jobs[i]
j = bisect_left(jobs, e, lo=i + 1, key=lambda x: x[0])
return max(dfs(i + 1), p + dfs(j))
jobs = sorted(zip(startTime, endTime, profit))
n = len(profit)
return dfs(0)Continue Topic
array
Practice more edge cases under the same topic.
arrow_forwardauto_awesomeContinue Pattern
State transition dynamic programming
Expand the same solving frame across more problems.
arrow_forwardsignal_cellular_altSame Difficulty Track
Hard
Stay on this level to stabilize interview delivery.
arrow_forward