LeetCode刷题之826. 安排工作以达到最大收益

你有 n 个工作和 m 个工人。给定三个数组: difficulty, profit 和 worker ,其中:

    difficulty[i] 表示第 i 个工作的难度,profit[i] 表示第 i 个工作的收益。
    worker[i] 是第 i 个工人的能力,即该工人只能完成难度小于等于 worker[i] 的工作。

每个工人 最多 只能安排 一个 工作,但是一个工作可以 完成多次 。

    举个例子,如果 3 个工人都尝试完成一份报酬为 $1 的同样工作,那么总收益为 $3 。如果一个工人不能完成任何工作,他的收益为 $0 。

返回 在把工人分配到工作岗位后,我们所能获得的最大利润 。

示例 1:

输入: difficulty = [2,4,6,8,10], profit = [10,20,30,40,50], worker = [4,5,6,7]
输出: 100
解释: 工人被分配的工作难度是 [4,4,6,6] ,分别获得 [20,20,30,30] 的收益。

这题就是直接让我们给worker安排合适的工作并且收益达到最大。difficulty 和 profit分别代表工作难度和相应的收益。如果能把diffculty和profit放在一起并根据收益排序,我们就能根据收益一个个安排工作,直到把所有人安排完。然后得到最大收益。当然你也能根据工作难度进行排序进行计算。不过稍微麻烦点。

本题解根据收益排序,关键是用什么来存收益和工作难度,我用了两种方法,一种是利用hashmap的键值对结构然后根据key或value排序,另外一种就是创建一个类,继承Comparable接口用Arrays.sort直接排序。从最大收益开始,把对应的工作难度在工人对应工作难度数组里进行二分查找,找到大于最大收益的工作难度边界,然后求出人数。知道把所有人安排工作。

1、创建新类,用对象数组排序

class Solution {
     public static int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
        
        Work work[]=new Work[difficulty.length];

        for(int i=0;i<difficulty.length;i++){
            work[i]=new Work(difficulty[i],profit[i]);
        }

        Arrays.sort(work);
        Arrays.sort(worker);
        int totalMoney=0;
        int pcount=0;
        int total=0;
        for(int i=work.length-1;i>=0;i--){
            
            if(work[i].difficulty>worker[worker.length-1]){
                totalMoney+=0;
            }else{
                if(total==worker.length) break;//所有人都有工作就直接退出

                int left=0,right=worker.length-1;// 60 

                while(left<right){
                    int mid=((right-left)>>1)+left;

                    if(worker[mid]>=work[i].difficulty){
                        right=mid;
                    }else{
                        left=mid+1;
                    }
                }
                pcount=worker.length-left-total;//还未安排工作且符合工作难度的人数
                 if(pcount<=0) continue;//由于收益高的不一定就是工作难度高的所以pcount有可能是负数
                total+=pcount;//安排过工作的人数
                totalMoney+=pcount*work[i].profit;
            }
        }
        return totalMoney;
    }
}
class Work implements Comparable<Work>{
        
        int difficulty;

        int profit;

        public Work(int difficulty,int profit){
            this.difficulty=difficulty;
            this.profit=profit;
        }  

        public int compareTo(Work work){
            return this.profit-work.profit;
        }
}

2、hashmap

class Solution {
     public static int maxProfitAssignment(int[] difficulty, int[] profit, int[] worker) {
        HashMap<Integer, Integer> map=new HashMap<>();

        Arrays.sort(worker);

         for(int i=0;i<difficulty.length;i++){
            if(map.get(difficulty[i])!=null){
                if(map.get(difficulty[i])<profit[i]){
                    map.put(difficulty[i],profit[i]);//由于有可能有重复的工作难度利用hashmap的不重复性只存最大收益的
                }
            }else{
                map.put(difficulty[i],profit[i]);
            }

        }


        List<Map.Entry<Integer, Integer>> list = new ArrayList<>(map.entrySet());//把map里的键值对转为entry对象 

        Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {//然后实现Compartor实现排序
            @Override
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o1.getKey()-o2.getKey();
            }
        });
        int maxProfit=0;
        int totalSalary=0;
        int oldMaxProfit=0;
        for(Map.Entry<Integer, Integer> i:list){
            int left=0,right=worker.length-1;
            if(i.getKey()>worker[worker.length-1]) break;

            if(maxProfit<map.get(i.getKey())){
                oldMaxProfit=maxProfit;
                maxProfit=i.getValue();

                while(left<right){
                    int mid=(left+right)>>1;

                    if(worker[mid]>=i.getKey()){
                        right=mid;
                    }else{
                        left=mid+1;
                    }
                }

                totalSalary-=oldMaxProfit*(worker.length-right);
                totalSalary+=maxProfit*(worker.length-right);
            }
        }
        return totalSalary;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值