1235. Maximum Profit in Job Scheduling
09/19/2021
Last updated
09/19/2021
Last updated
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.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.Input: startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
Output: 6// DFS with memoization
class Solution {
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
Map<Integer, Integer> cache = new HashMap<>();
int[][] tasks = new int[startTime.length][3];
for (int i = 0; i < startTime.length; ++i) {
tasks[i] = new int[] {startTime[i], endTime[i], profit[i]};
}
Arrays.sort(tasks, (t1, t2) -> {
if (t1[0] != t2[0]) return Integer.compare(t1[0], t2[0]);
else return Integer.compare(t2[1], t1[1]); // 结束晚的在前
});
return getMaxProfitStartFrom(tasks[0][0], tasks, cache);
}
private int getMaxProfitStartFrom(int start, int[][] tasks, Map<Integer, Integer> cache) {
int nextIndex = searchNextStartTaskIndex(start, tasks);
if (nextIndex == -1) {
return 0;
}
int[] task = tasks[nextIndex];
if (cache.containsKey(task[0])) {
return cache.get(task[0]);
}
// 分别考虑schedule相同start time的所有task
int maxProfit = 0;
for (int i = nextIndex; i < tasks.length; ++i) {
if (i > nextIndex && tasks[i][0] != task[0]) {
break;
}
maxProfit = Math.max(maxProfit,
tasks[i][2] + getMaxProfitStartFrom(tasks[i][1], tasks, cache));
}
// 考虑 skip 当前start time的所有task
maxProfit = Math.max(maxProfit, getMaxProfitStartFrom(task[0] + 1, tasks, cache));
cache.put(task[0], maxProfit);
return maxProfit;
}
// 找到开始时间>= start的第一个task的index, return -1 if not found
private int searchNextStartTaskIndex(int start, int[][] tasks) {
int left = 0, right = tasks.length - 1;
while (left + 1 < right) {
int mid = (left + right) / 2;
if (tasks[mid][0] < start) {
left = mid;
} else {
right = mid;
}
}
if (tasks[left][0] >= start) return left;
else if (tasks[right][0] >= start) return right;
else return -1;
}
}
//DP:
class Solution {
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
int N = startTime.length;
TreeMap<Integer, Integer> dp = new TreeMap<>();
int[][] tasks = new int[N][3];
for (int i = 0; i < N; ++i) {
tasks[i] = new int[] {startTime[i], endTime[i], profit[i]};
}
Arrays.sort(tasks, (t1, t2) -> Integer.compare(t1[0], t2[0]));
for (int i = tasks.length - 1; i >= 0; --i) {
int[] task = tasks[i];
int start = task[0], end = task[1], p = task[2];
Map.Entry<Integer, Integer> entryAfterEnd = dp.ceilingEntry(end);
int val = entryAfterEnd == null ? p : p + entryAfterEnd.getValue();
Map.Entry<Integer, Integer> entryAfterStart = dp.firstEntry();
if (entryAfterStart != null && entryAfterStart.getValue() > val) {
dp.put(start, entryAfterStart.getValue());
} else {
dp.put(start, val);
}
}
return dp.firstEntry().getValue();
}
}