2071. 你可以安排的最多任务数目
思路:二分查找+贪心;题目的意思就是找到最大可以完成的任务数量l,对于这个任务数量l,一定满足,任务里最小的l个,和工人里最大的l个,它们之间满足条件。那么我们就用二分查找来找到最大的这个l,这里的时间复杂度为0(logn)。对于check函数,时间复杂度是0(nlogn)。最终的时间复杂度为0(nlogn * logn )
check函数里的贪心:我们对任务的难度升序判断,对于最小的任务,那么我们肯定是希望最小力量的工人来完成,如果不能完成,那肯定就需要吃药啦。如果吃药可以完成这个最小的任务,我们就查找吃完药后,这个工人可以完成的最大任务,这里就用到了贪心的思想。
注意:需要减少erase使用的次数,卡了我小一个小时的超时。
class Solution {
public:
int n,m;
vector<int> tasks_copy,workers_copy;
bool check(int u, int pills, int strength){
bool flag=1;
vector<int> ta,wo;
for(int i=0;i<u;i++){
ta.push_back(tasks_copy[i]);
wo.push_back(workers_copy[m-u+i]);
}
int j=0,k=0;//这里就是为了减少erase的次数,非常耗时
for(int i=0;i<u;i++){
if(ta[k]<=wo[j]){
k++;
j++;
}else if(pills && ta[k]<=(wo[j]+strength)){
pills--;
ta.erase(upper_bound(ta.begin()+k,ta.end(),wo[j]+strength)-1);
j++;
}else{
flag=0;
break;
}
}
return flag;
}
int maxTaskAssign(vector<int>& tasks, vector<int>& workers, int pills, int strength) {
n=tasks.size(),m=workers.size();
sort(tasks.begin(),tasks.end());
sort(workers.begin(),workers.end());
tasks_copy=tasks;
workers_copy=workers;
int l=0,r=min(n,m);
while(l<r){
int mid=(l+r+1)/2;
if(check(mid,pills,strength)) l=mid;
else r=mid-1;
}
return l;
}
};