你打算利用空闲时间来做兼职工作赚些零花钱。
这里有 n
份兼职工作,每份工作预计从 startTime[i]
开始到 endTime[i]
结束,报酬为 profit[i]
。
给你一份兼职工作表,包含开始时间 startTime
,结束时间 endTime
和预计报酬 profit
三个数组,请你计算并返回可以获得的最大报酬。
注意,时间上出现重叠的 2 份工作不能同时进行。
如果你选择的工作在时间 X
结束,那么你可以立刻进行在时间 X
开始的下一份工作。
1 <= startTime.length == endTime.length == profit.length <= 5 * 10^4
1 <= startTime[i] < endTime[i] <= 10^9
1 <= profit[i] <= 10^4
输入:startTime = [1,2,3,3], endTime = [3,4,5,6], profit = [50,10,40,70]
输出:120
解释:
我们选出第 1 份和第 4 份工作,
时间范围是 [1-3]+[3-6],共获得报酬 120 = 50 + 70。
输入:startTime = [1,2,3,4,6], endTime = [3,5,10,6,9], profit = [20,20,100,70,60]
输出:150
解释:
我们选择第 1,4,5 份工作。
共获得报酬 150 = 20 + 70 + 60。
输入:startTime = [1,1,1], endTime = [2,3,4], profit = [5,6,4]
输出:6
这道题是二分+dp+离散化+01背包问题:
所有的区间
按照endTime
进行从小到大排序,因为endTime
区间很大,所以我们需要进行离散化,接下来就假设endTime[i] -> i
,也就是第i
个endTime
对应第i
个索引所有的区间
,假设当前的区间为``j
,他的endTime -> k
,startTime -> i
,那么我们可以试着找到endTime2 <= startTime,endTime2 -> k2
,那么就可以dp[k]=max(dp[k] ,j的profit + dp[k2])
这个j区间
不一定是最好的,可能选上一个区间的endTime
的值更大呢,所以就是dp[k]=max(dp[k],dp[k-1])
import org.omg.PortableServer.POA;
import java.util.*;
public class test27 {
class Point
{
int start;
int end;
int profit;
}
class Mycom implements Comparator<Point>
{
@Override
public int compare(final Point o1, final Point o2) {
if(o1.end < o2.end) return -1;
else if (o1.end == o2.end && o1.start < o2.start) return -1;
return 1;
}
}
public int search(int[] xs,int key)
{
int left = 0;
int right = xs.length - 1;
int mid;
while (left <= right)
{
mid = (left + right) / 2;
if(xs[mid] > key) right = mid - 1;
else
{
left = mid + 1;
}
}
left = left - 1;
return left;
}
public int jobScheduling(int[] startTime, int[] endTime, int[] profit) {
int ans = 0;
int index = 0;
int length = startTime.length;
Point[] ps = new Point[length];
int [] dps;
int [] ends;
Set<Integer> set = new HashSet<>();
Map<Integer,Integer> map;
for(int i = 0;i < length;i++)
{
ps[i] = new Point();
ps[i].start = startTime[i];
ps[i].end = endTime[i];
ps[i].profit = profit[i];
if(set.contains(ps[i].end)) continue;
set.add(ps[i].end);
}
dps = new int[set.size()];
ends = new int[set.size()];
map = new HashMap<>(set.size());
for(int i = 0; i < dps.length;i++) dps[i] = 0;
Arrays.sort(ps,new Mycom());
for(int i = 0;i < length;i++)
{
if(map.containsKey(ps[i].end)) continue;
map.put(ps[i].end,index);
ends[index++] = ps[i].end;
}
for(int i = 0;i < length;i++)
{
int lag = search(ends,ps[i].start);
int endindex = map.get(ps[i].end);
if(lag == -1)
{
dps[endindex] = Math.max(dps[endindex],ps[i].profit);
}
else
{
dps[endindex] = Math.max(dps[endindex],ps[i].profit + dps[lag]);
}
if(endindex - 1 >= 0)
{
dps[endindex] = Math.max(dps[endindex - 1],dps[endindex]);
}
ans = Math.max(dps[endindex],ans);
}
return ans;
}
public static void main(String[] args) {
test27 of = new test27();
int [] startTime = {4,2,4,8,2};
int [] endTime = {5,5,5,10,8};
int [] profit = {1,2,8,10,4};
System.out.println(of.jobScheduling(startTime,endTime,profit));
// System.out.println(of.search(array,0));
// System.out.println(of.search(array,1));
// System.out.println(of.search(array,2));
// System.out.println(of.search(array,3));
// System.out.println(of.search(array,4));
// System.out.println(of.search(array,5));
// System.out.println(of.search(array,6));
}
}