/** 贪心:要想使子集分数最大,应选取values中较大的值。
* 思路:使用一个哈希表来记录每个标签使用的次数,相同标签使其不超过useLimit限制
* 对values进行降序排序,并对其进行遍历只要标签使用次数不超过限制就将较大值
* 加入结果中。
* 注意:因为不能改变values数组的次序所以不能直接对其进行排序,所以使用一个
* 下标数组idx进行排序,idx[0]就是values中第一个最大值,idx[1]就是values
* 中第二大的值,以此类推。
* map中getOrDefault()方法:获取key对应的value,若map中没有key关键字,则返回自己设置的返回值。
*/
public class L1090 {
public int largestValsFromLabels(int[] values, int[] labels, int numWanted, int useLimit) {
int n = values.length;
Integer[] idx = new Integer[n];
for (int i = 0; i < n; i++) {
idx[i] = i;
}
//使用下标函数对values实现排序
Arrays.sort(idx,(a,b) -> values[b] - values[a]);
Map<Integer,Integer> map = new HashMap<>();
//choose表示子集的大小,lab表示标签
int sums = 0,choose = 0,lab = 0;
for (int i = 0; i < n && choose < numWanted; i++) {
//获取values中第i个最大值的标签
lab = labels[idx[i]];
//标签数量不能大于限制,因为lab是从0开始所以等于useLimit
if (map.getOrDefault(lab,0) == useLimit)
continue;
choose++;
//添加到结果中
sums += values[idx[i]];
//更改标签的使用次数
map.put(lab,map.getOrDefault(lab,0)+1);
}
return sums;
}
}