题目描述
我们有一个项的集合,其中第 i 项的值为 values[i],标签为 labels[i]。
我们从这些项中选出一个子集 S,这样一来:
|S| <= num_wanted
对于任意的标签 L,子集 S 中标签为 L 的项的数目总满足 <= use_limit。
返回子集 S 的最大可能的 和。
示例:
输入:values = [5,4,3,2,1], labels = [1,1,2,2,3], num_wanted = 3, use_limit = 1
输出:9
总结
SDC把两个需要同步排序的数组用 二进制的方法解决了
EC需要数组默认排序
Sample & Demo Code
class Solution {
public int largestValsFromLabels(int[] values, int[] labels, int num_wanted, int use_limit) {
int maxLabel = 0;
for(int i = 0; i < values.length; i++) {
values[i] = (values[i] << 16) | labels[i]; // ! ! !
maxLabel = Math.max(labels[i], maxLabel);
}
Arrays.sort(values); //values(升序)优先,再按labels(升序)
int res = 0, L = 0;
int[] counts = new int[maxLabel+1]; //缺点:当labels有特别大的值的时候空间复杂度会很高
for(int i = values.length-1; i >= 0 && L < num_wanted; i--) {
if(counts[values[i] & 0xFFFF]++ < use_limit) { // <<16 和 &0xFFFF刚好能对消
res += (values[i] >>> 16);
L++;
}
}
return res;
}
}
ERROR Code
class Solution {
public int largestValsFromLabels(int[] values, int[] labels, int num_wanted, int use_limit) {
int L = 0;
Map<Integer, Integer> map = new HashMap<>();
int res = 0;
for(int i = 0; i < values.length && L < num_wanted; i++) {
if(map.getOrDefault(labels[i], 0) == 0) {
map.put(labels[i], 1);
res += values[i];
L++;
}else if(map.get(labels[i]) < use_limit) {
map.put(labels[i], map.get(labels[i])+1);
res += values[i];
L++;
}else if(map.get(labels[i]) >= use_limit) {
while(i < values.length-1 && labels[i] == labels[i+1]) i++;
}
}
return res;
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-values-from-labels

本文介绍了一种解决最大价值标签子集问题的算法,通过将两个数组进行二进制同步排序,确保在限定数量和标签使用次数下,选择具有最大价值的子集。文章对比了两种解决方案,一种是通过修改数组元素实现同步排序,另一种是使用哈希映射记录标签使用次数。
687

被折叠的 条评论
为什么被折叠?



