你有 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;
}
}