本文已参与「新人创作礼」活动,一起开启掘金创作之路。
一、题目描述:
1090. 受标签影响的最大值 - 力扣(LeetCode) (leetcode-cn.com)
我们有一个 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.length
- 1 <= n <= 2 * 10^4
- 0 <= values[i], labels[i] <= 2 * 10^4
- 1 <= numWanted, useLimit <= n
二、思路分析:
-
首先要清楚一点,先考虑的是如何使子集的和(result)最大,其次再考虑每个标签所用数目(count_limit)<=use_limit,最后才考虑所选项的总数(count)<=num_wanted;
-
先将每个value与其对应的label组成一对,保存在一个列表中,并按value大小从大到小排序;
-
之后,从头开始遍历,这样可以保证总是先拿到目前最大的value,同时去考虑这个value对应的labal的数目是否超过了use_limit;
-
要注意的是,可能存在count大小不足num_wanted的情况
三、AC 代码:
class Solution:
def largestValsFromLabels(self, values: List[int], labels: List[int], num_wanted: int, use_limit: int) -> int:
length = len(values)
result_list = []
for i in range(length):
result_list.append((values[i], labels[i]))
result_list.sort(reverse=True)
count_limit = {}
result, count = 0, 0
for i in range(length):
if result_list[i][1] not in count_limit:
result += result_list[i][0]
count += 1
count_limit[result_list[i][1]] = 1
elif count_limit[result_list[i][1]] < use_limit:
result += result_list[i][0]
count += 1
count_limit[result_list[i][1]] += 1
if count == num_wanted:
break
return result
四、总结:
最后说一点的是,当你明白题意的时候,这道题你就已经成功一半了(含蓄吐槽)