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:
Input: 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:
Input: 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:
Input: startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4] Output: 6
Constraints:
1 <= startTime.length == endTime.length == profit.length <= 5 * 104
1 <= startTime[i] < endTime[i] <= 109
1 <= profit[i] <= 104
This problem asks to find the maximum profit achievable by scheduling jobs without overlapping time ranges. We are given three arrays: startTime
, endTime
, and profit
, each representing the start time, end time, and profit of a job, respectively.
The most efficient approach uses dynamic programming combined with binary search for optimal performance.
Data Structure: We'll create a custom data structure (e.g., a struct or class) to represent each job, combining startTime
, endTime
, and profit
. This will help in sorting and managing jobs easily.
Sorting: Sort the jobs by their end times in ascending order. This is crucial for efficient dynamic programming.
Dynamic Programming: Create a dp
array where dp[i]
represents the maximum profit achievable considering jobs up to index i
. We initialize dp[0] = 0
.
Iteration and Binary Search: Iterate through the sorted jobs. For each job i
:
i
: This is simply dp[i]
.j
using binary search on the sorted jobs based on their start times. Binary search is efficient for finding the latest non-overlapping job. This works because the jobs are sorted by their end times.i
: This is dp[j] + profit[i]
.dp[i+1]
as the maximum of these two values.Result: The final element dp[n]
(where n
is the number of jobs) will contain the maximum profit.
dp
array and the job data structure.import bisect
def jobScheduling(startTime, endTime, profit):
jobs = sorted(zip(endTime, startTime, profit)) # Sort by endTime
n = len(profit)
dp = [0] * (n + 1) # Initialize DP array
for i, (et, st, p) in enumerate(jobs):
j = bisect.bisect_right([job[0] for job in jobs], st) # Binary search for latest non-overlapping job
dp[i + 1] = max(dp[i], dp[j] + p) # Update DP array
return dp[n]
import java.util.Arrays;
import java.util.Comparator;
class Solution {
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
int n = profit.length;
int[][] jobs = new int[n][3];
for (int i = 0; i < n; i++) {
jobs[i] = new int[]{endTime[i], startTime[i], profit[i]}; // Store as (endTime, startTime, profit)
}
Arrays.sort(jobs, Comparator.comparingInt(a -> a[0])); // Sort by endTime
int[] dp = new int[n + 1];
for (int i = 0; i < n; i++) {
int j = binarySearch(jobs, i, jobs[i][1]); // Binary search for latest non-overlapping job
dp[i + 1] = Math.max(dp[i], dp[j] + jobs[i][2]); //Update dp array
}
return dp[n];
}
private int binarySearch(int[][] jobs, int right, int target) {
int left = 0;
while (left < right) {
int mid = (left + right) / 2;
if (jobs[mid][1] > target) { // Check if the job does not overlap
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}
The Java and Python solutions demonstrate the core dynamic programming and binary search logic. Other languages (C++, JavaScript, etc.) would follow a similar structure, adapting the syntax as needed. Remember to handle edge cases appropriately (e.g., empty input arrays).