受标签影响的最大值
难度:
标签:
题目描述
代码结果
运行时间: 35 ms, 内存: 20.7 MB
/*
* 思路:
* 1. 创建一个数组表示每个元素的值和标签。
* 2. 按照值从大到小对元素进行排序。
* 3. 使用一个哈希表记录每个标签的使用次数。
* 4. 使用Stream API遍历排序后的数组,选择不超过 numWanted 个元素,并且每个标签不超过 useLimit 次。
* 5. 返回选择的元素值之和。
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public int largestValsFromLabels(int[] values, int[] labels, int numWanted, int useLimit) {
int n = values.length;
List<int[]> items = IntStream.range(0, n)
.mapToObj(i -> new int[]{values[i], labels[i]})
.sorted((a, b) -> Integer.compare(b[0], a[0]))
.collect(Collectors.toList());
Map<Integer, Long> labelCount = new HashMap<>();
int[] sum = {0};
int[] count = {0};
items.stream()
.filter(item -> {
int label = item[1];
labelCount.put(label, labelCount.getOrDefault(label, 0L) + 1);
if (labelCount.get(label) <= useLimit && count[0] < numWanted) {
sum[0] += item[0];
count[0]++;
return true;
} else {
labelCount.put(label, labelCount.get(label) - 1);
return false;
}
})
.collect(Collectors.toList());
return sum[0];
}
}
解释
方法:
此题解的基本思路是首先将元素按照其值进行排序,然后从值最大的元素开始选择,确保不超过每个标签的使用限制 `useLimit` 和总数不超过 `numWanted`。这样可以保证所选的子集有可能是最大值。具体步骤包括:
1. 创建一个包含值和标签对的列表。
2. 将这个列表按值进行排序。
3. 使用一个字典来跟踪每个标签已经使用的次数。
4. 从列表的末尾(值最大的位置)开始,如果当前元素的标签使用次数没有达到 `useLimit`,则将其加入到结果中,并更新标签的使用次数。
5. 检查是否已经选择了 `numWanted` 个元素,如果是,则结束选择。
6. 最后返回所有选中元素值的总和。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
在算法中如何保证当标签的使用次数已达到useLimit时,不再选择该标签的元素?
▷🦆
对于包含重复值但不同标签的元素,此算法是如何处理的?例如values中多个元素值相同但标签不同。
▷🦆
排序后为什么选择从列表末尾开始迭代?迭代从最大值开始有什么特别的优势吗?
▷🦆
如果在达到numWanted选择的数量之前就遍历完了所有的元素,这种情况下算法的输出会怎样?
▷