题目描述
有一个Job工作的数据结构,每一种工作有难度和报酬,现在,给你一个int类型的数组,表示各个小伙伴的能力,只有小伙伴的能力大于等于工作难度,才能从事那份工作,现在,请你求出各个小伙伴,在其能力能胜任的工作中,能获取最高报酬的工作?假设每种工作都有无限个岗位。
思路分析
此题,咋一看就像是经典的贪心算法问题,对吧?我的第一反应也是贪心算法,首先,按照工作难度从小到大放入一个小根堆中,然后,把小于当前能力的出堆,再进入一个大根堆中,大根堆根据报酬组织,返回堆顶元素,就是最大报酬的工作。
但是,用上面的贪心解题的话,能解是能解,不过,有一些问题,首先,此题的题意是每种工作有无限个,而堆则是直接弹出了,因此,上述解法更适合于工作数量有限的问题。其次,上述问题给你的是一个能力的数组,最终让你返回的也是一个最大报酬数组,而不是一个人,因此,每一个人都得重新构建堆结构,这复杂度就有点高了,因此,虽然此题很像是用贪心算法解决的题目,实则贪心算法并不合适。
如果贪心算法不合适,那就只能考虑使用其他技巧了,题目给你一个能力的数组,最终返回最高报酬的数组,这不就类似于让你实现一个结构,结构中,先根据难度排序,再根据报酬排序,当你在该结构中找到小于该能力的位置,然后,在左边再找第一个也就是最大的报酬,就是答案。
具体分析题目,首先按照难度排序,在同一个难度时,只有最高报酬的才有效,对吧?因为只会选择最高报酬的,其次,如果难度更高的工作,报酬反而低,那么,这个工作也永远都不会被选择,对吧?因此,可以根据这两点,筛选出剩下的,要求难度依次上升,同时报酬也依次上升,此时,输入一个能力值,小于该能力值的第一份工作,就是答案,因为此结构中,已经把不符合顺序的排除掉了。
代码
数据结构
class Job{
int hard;
int money;
public Job(int hard,int money){
this.hard=hard;
this.money=money;
}
}
class MyComparator implements Comparator<Job>{
@Override
public int compare(Job o1, Job o2) {
//比较器,如果hard相同就比较money,money从大到小
return o1.hard==o2.hard? o2.money-o1.money: o1.hard-o2.hard;
}
}
代码
public static int[] f1(Job[] jobs,int[] abilitys){
//利用比较器排序,hard从小到大,money从大到小
Arrays.sort(jobs,new MyComparator());
//保存结果
int[] res=new int[abilitys.length];
//有序表,key是hard,value是money
TreeMap<Integer,Integer> map=new TreeMap<>();
//把第一个放进去,key最小value最大的值
map.put(jobs[0].hard,jobs[0].money);
Job pre=jobs[0];
//只保留相同难度的报酬最大值,同时,如果难度增加报酬没增加的直接排除
for (int i = 1; i < jobs.length; i++) {
if(jobs[i].hard!=pre.hard&&jobs[i].money>pre.money){
pre=jobs[i];
map.put(jobs[i].hard,jobs[i].money);
}
}
//map.floorKey函数返回小于key的第一个数
for (int i = 0; i < abilitys.length; i++) {
if(map.floorKey(abilitys[i])!=null){
res[i]=map.get(map.floorKey(abilitys[i]));
}else {
res[i]=0;
}
}
return res;
}