(nice!!!)(LeetCode每日一题)2071. 你可以安排的最多任务数目(二分查找、贪心)

题目:2071. 你可以安排的最多任务数目

在这里插入图片描述
在这里插入图片描述

思路:二分查找+贪心,题目的意思就是找到最大可以完成的任务数量l,对于这个任务数量l,一定满足,任务里最小的l个,和工人里最大的l个,它们之间满足条件。那么我们就用二分查找来找到最大的这个l,这里的时间复杂度为0(logn)。对于check函数,时间复杂度是0(nlogn)。最终的时间复杂度为0(nlogn * logn )

check函数里的贪心:我们对任务的难度升序判断,对于最小的任务,那么我们肯定是希望最小力量的工人来完成,如果不能完成,那肯定就需要吃药啦。如果吃药可以完成这个最小的任务,我们就查找吃完药后,这个工人可以完成的最大任务,这里就用到了贪心的思想。

class Solution {
public:
    bool check(int u,vector<int>& tasks, vector<int>& workers, int pills, int strength){
        bool flag=true;
        vector<int> ta,wo;
        int m=workers.size();
        // 贪心
        for(int i=0;i<u;i++){
            ta.push_back(tasks[i]);
            wo.push_back(workers[m-u+i]);
        }
        int i=0,j=0;
        while(j<u){
            if(ta[i]<=wo[j]){
                i++,j++;
            }else if(pills &&ta[i]<=wo[j]+strength){
            	//吃药后,选最大可以解决的任务
                ta.erase(upper_bound(ta.begin()+i,ta.end(),wo[j]+strength)-1);
                pills--;
                j++;
            }else{
                flag=0;
                break;
            }
        }
        return flag;

    }

    int maxTaskAssign(vector<int>& tasks, vector<int>& workers, int pills, int strength) {
        sort(tasks.begin(),tasks.end());
        sort(workers.begin(),workers.end());
        int n=tasks.size(),m=workers.size();
        int l=0,r=min(n,m);
        //二分查找
        while(l<r){
            int mid=(l+r+1)/2;
            if(check(mid,tasks,workers,pills,strength))l=mid;
            else r=mid-1;
        }
        return l;
    }
};

JAVA版本:

class Solution {

    int findd(List<Integer> ta,int u){
        int l=0,r=ta.size()-1;
        while(l<=r){
            int mid=(l+r)/2;
            if(ta.get(mid)<=u) l=mid+1;
            else r=mid-1;
        }
        return l-1;
    }
    boolean check(int u,int[] tasks, int[] workers, int pills, int strength){
        boolean flag=true;
        List<Integer> ta=new ArrayList<Integer>();
        List<Integer> wo=new ArrayList<Integer>();

        int m=workers.length;
        for(int i=0;i<u;i++){
            ta.add(tasks[i]);
            wo.add(workers[m-u+i]);
        }
        int i=0,j=0;
        while(j<u){
            if(ta.get(i)<=wo.get(j)){
                i++;
                j++;
            }else if(pills!=0 &&ta.get(i)<=wo.get(j)+strength){
                ta.remove(findd(ta,wo.get(j)+strength));
                pills--;
                j++;
            }else{
                flag=false;
                break;
            }
        }
        return flag;

    }

    public int maxTaskAssign(int[] tasks, int[] workers, int pills, int strength) {
        Arrays.sort(tasks);
        Arrays.sort(workers);
        int n=tasks.length,m=workers.length;
        int l=0,r=Math.min(n,m);
        while(l<r){
            int mid=(l+r+1)/2;
            if(check(mid,tasks,workers,pills,strength))l=mid;
            else r=mid-1;
        }
        return l;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值