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, you need to output the maximum profit you can take such that there are no 2 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.
思路:用dp来做,dp[i]代表到i为止的当前能够得到的最大值,dp[i] = Math.max(dp[i - 1], currProfit + 最后一个不相交的dp[l]); 注意jobs排序是按照end排序;
class Solution {
class Node {
public int start;
public int end;
public int profit;
public Node(int start, int end, int profit) {
this.start = start;
this.end = end;
this.profit = profit;
}
}
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
int n = startTime.length;
Node[] nodes = new Node[n];
for(int i = 0; i < n; i++) {
nodes[i] = new Node(startTime[i], endTime[i], profit[i]);
}
Arrays.sort(nodes, (a, b) -> (a.end - b.end));
// dp[i] 表示的物理意义是,到目前为止能得到的最大value;
// 递推: dp[i] = Max(dp[i - 1], dp[j] + value[i]), j就是不覆盖i,最近的interval;
int[] dp = new int[n];
dp[0] = nodes[0].profit;
// dp[i] = Math.max(dp[i - 1], curprofit + dp[j]), where dp[j] is the last j which is not overlap with i;
for(int i = 1; i < dp.length; i++) {
int curprofit = nodes[i].profit;
int index = findIndex(nodes, i);
if(index != -1) {
curprofit += dp[index];
}
dp[i] = Math.max(dp[i - 1], curprofit);
}
return dp[n - 1];
}
// 按照end升序排序之后,找离当前interval最近的interval;
private int findIndex(Node[] nodes, int i) {
int start = 0; int end = nodes.length - 1;
while(start + 1 < end) {
int mid = start + (end - start) / 2;
if(nodes[mid].end <= nodes[i].start) {
start = mid;
} else {
end = mid;
}
}
if(nodes[end].end <= nodes[i].start) {
return end;
}
if(nodes[start].end <= nodes[i].start) {
return start;
}
return -1;
}
}