题目描述:
我们有一个 n
项的集合。给出两个整数数组 values
和 labels
,第 i
个元素的值和标签分别是 values[i]
和 labels[i]
。还会给出两个整数 numWanted
和 useLimit
。
从 n
个元素中选择一个子集 s
:
- 子集
s
的大小 小于或等于numWanted
。 s
中 最多 有相同标签的useLimit
项。
一个子集的 分数 是该子集的值之和。
返回子集 s
的最大 分数 。
官方的中文翻译着实稀烂,下面我来解释一下题目意思:
意思就是一共有几个物品,每个物品都有自己的重量和标签,现在要拿总数不超过numWanted个物品,而且每种物品最多拿useLimit个,求最重可以拿多重的物品。
明确题意后,按重量排序后使用哈希表记录每种物品拿的个数,贪心即可。
源代码:
// 受标签影响的最大值
function largestValsFromLabels(values, labels, numWanted, useLimit) {
// 将两个数组合并
const goods = values.map((item, index) => {
return item = [item, labels[index]];
});
// 按value排序
goods.sort((a, b) => {
return b[0] - a[0];
});
const useMap = new Map();
let res = 0;
// 贪心,因为数组已经按value降序排序,所以从数组第一个开始累加分数,当前标签用完了就接着用下一个
for (let i = 0; i < values.length; ++i) {
// 判断如果当前标签的使用次数已经达到了上限,就跳过,执行下一次循环
if (useMap.get(goods[i][1]) === useLimit) {
continue;
}
// 记录已使用标签的次数
useMap.set(goods[i][1], (useMap.get(goods[i][1]) || 0) + 1);
res += goods[i][0];
numWanted--;
if (numWanted === 0) {
break;
}
}
return res;
};
console.log(largestValsFromLabels([9, 8, 8, 7, 6], [0, 0, 0, 1, 1], 3, 1));