题目:受标签影响的最大值
我们有一个 n 项的集合。给出两个整数数组 values 和 labels ,第 i 个元素的值和标签分别是 values[i] 和 labels[i]。还会给出两个整数 numWanted 和 useLimit 。
从 n 个元素中选择一个子集 s :
- 子集
s的大小 小于或等于numWanted。 s中 最多 有相同标签的useLimit项。
一个子集的 分数 是该子集的值之和。
返回子集 s 的最大 分数 。
示例 1:
输入: values = [5,4,3,2,1], labels = [1,1,2,2,3], numWanted = 3, useLimit = 1
输出: 9
解释: 选出的子集是第一项,第三项和第五项。
示例 2:
输入: values = [5,4,3,2,1], labels = [1,3,3,3,2], numWanted = 3, useLimit = 2
输出: 12
解释: 选出的子集是第一项,第二项和第三项。
示例 3:
输入: values = [9,8,8,7,6], labels = [0,0,0,1,1], numWanted = 3, useLimit = 1
输出: 16
解释: 选出的子集是第一项和第四项。
提示:
n == values.length == labels.length1 <= numWanted, useLimit <= n
解题思路
这道题我们要在label不超过useLimit的情况下,尽可能地找到比较大的value,可以将value-label这个组合包装到一个类中,然后存入数组pairs中按照value降序排序。 之后遍历pairs数组,如果当前value的label数量没有超出限制,则将value值累加。 我们用一个HashMap来存储已经使用的label数量。
先用map记录已经使用的某个label的数量 然后将values和labels转换成一个二维数组,对这个数组的value从大到小排序。 然后遍历二维数组,过滤结果
贪心的把所有节点按照values排序,依次选择加入结果集,当节点满足要求即(相同labels数目<=use_limit)加入贪心结果集,反之跳过,直至循环结束(结果集总个数< num_wanted)
代码实现
public int largestValsFromLabels(int[] values, int[] labels, int num_wanted, int use_limit) {
HashMap < Integer, Integer > map = new HashMap < > ();
for (int i: labels) {
map.put(i, 0);
}
int[][] pair = new int[values.length][2];
for (int i = 0; i < values.length; i++) {
pair[i][0] = values[i];
pair[i][1] = labels[i];
}
Arrays.sort(pair, (a, b) - > (b[0] - a[0]));
int sum = 0;
for (int i = 0; i < pair.length; i++) {
int value = pair[i][0];
int label = pair[i][1];
if (num_wanted > 0 && map.get(label) < use_limit) {
num_wanted--;
map.put(label, map.get(label) + 1);
sum += value;
}
}
return sum;
}
运行结果
复杂度分析
- 空间复杂度:O(n)
- 时间复杂度:O(n^2)
在掘金(JUEJIN) 一起分享知识, Keep Learning!