We have n
jobs, where every job is scheduled to be done from startTime[i]
to endTime[i]
, obtaining a profit of profit[i]
. You're given the startTime
, endTime
and profit
arrays, return the maximum profit you can take such that there are no two jobs in the subset with overlapping time range.
If you choose a job that ends at time X
you will be able to start another job that starts at time X
.
Example 1:
startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]
Output: 120
Explanation: The subset chosen is the first and fourth job. Time range [1-3]+[3-6] , we get profit of 120 = 50 + 70.
Example 2:
startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60]
Output: 150
Explanation: The subset chosen is the first, fourth and fifth job. Profit obtained 150 = 20 + 70 + 60.
Example 3:
startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
Output: 6
Constraints:
1 <= startTime.length == endTime.length == profit.length <= 5 * 10^4
1 <= startTime[i] < endTime[i] <= 10^9
1 <= profit[i] <= 10^4
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The core idea is to explore every single possible combination of jobs we can take. We will check each combination to see if the jobs are compatible and then keep track of the best profit we've found so far.
Here's how the algorithm would work step-by-step:
def max_profit_job_scheduling_brute_force(start_times, end_times, profits):
number_of_jobs = len(start_times)
def is_overlapping(job_index, scheduled_jobs):
for scheduled_job_index in scheduled_jobs:
if max(start_times[job_index], start_times[scheduled_job_index]) < min(end_times[job_index], end_times[scheduled_job_index]):
return True
return False
def find_max_profit(current_job_index, scheduled_jobs):
# Base case: If we've considered all jobs
if current_job_index == number_of_jobs:
total_profit = 0
for job_index in scheduled_jobs:
total_profit += profits[job_index]
return total_profit
# Option 1: Exclude the current job
max_profit_excluding_job = find_max_profit(current_job_index + 1, scheduled_jobs)
# Option 2: Include the current job if it doesn't overlap
max_profit_including_job = 0
# Check for overlaps with previously scheduled jobs
if not is_overlapping(current_job_index, scheduled_jobs):
# Add the job and recurse
max_profit_including_job = find_max_profit(current_job_index + 1, scheduled_jobs + [current_job_index])
# Return the maximum of the two options
return max(max_profit_excluding_job, max_profit_including_job)
# Start the recursion with no jobs scheduled.
return find_max_profit(0, [])
The goal is to maximize your earnings by strategically picking the best set of jobs. The most efficient approach involves making ordered choices, skipping jobs that conflict with earlier, more profitable ones, and remembering the best profit we have seen so far.
Here's how the algorithm would work step-by-step:
def job_scheduling(start_time, end_time, profit):
jobs = sorted(zip(start_time, end_time, profit), key=lambda x: x[1])
number_of_jobs = len(jobs)
maximum_profit_at_time = [0] * number_of_jobs
maximum_profit_at_time[0] = jobs[0][2]
for i in range(1, number_of_jobs):
# Calculate profit including the current job
current_profit = jobs[i][2]
latest_non_overlapping_job = -1
# Find the latest non-overlapping job
for j in range(i - 1, -1, -1):
if jobs[j][1] <= jobs[i][0]:
latest_non_overlapping_job = j
break
if latest_non_overlapping_job != -1:
current_profit += maximum_profit_at_time[latest_non_overlapping_job]
# Choose max profit either including or excluding job
maximum_profit_at_time[i] = max(current_profit, maximum_profit_at_time[i - 1])
# The last value holds the max profit
return maximum_profit_at_time[number_of_jobs - 1]
Case | How to Handle |
---|---|
Empty startTime, endTime, or profit arrays | Return 0 immediately as no jobs can be scheduled with empty input. |
startTime, endTime, and profit arrays have different lengths | Throw an IllegalArgumentException or return an error code, as the input is invalid. |
Single job available | Return the profit of the single job if valid, as it's the maximum possible profit. |
Jobs with overlapping times but no profit | The solution should correctly determine that these jobs should not be scheduled, resulting in 0 profit from those jobs. |
Jobs with identical start and end times but different profits | Sorting by end time or a custom criteria must handle the case of identical end times, picking the job which helps maximize profit. |
Large number of jobs (scalability) | Dynamic programming with memoization or a similar efficient approach is needed to handle large input sizes without exceeding time limits. |
startTime and endTime values are large, leading to potential integer overflow during calculations | Use long data type for calculations or consider modulo operations if appropriate to prevent integer overflow. |
All jobs are mutually exclusive | The algorithm must correctly identify and sum the profits of all mutually exclusive jobs to determine the maximum profit. |