前言

Weekly Contest 141受标签影响的最大值

我们有一个项的集合,其中第 i 项的值为 values[i],标签为 labels[i]

我们从这些项中选出一个子集 S,这样一来:

  • |S| <= num_wanted
  • 对于任意的标签 L,子集 S 中标签为 L 的项的数目总满足 <= use_limit

返回子集 S 的最大可能的

示例1:

输入:values = [5,4,3,2,1], labels = [1,1,2,2,3], num_wanted = 3, use_limit = 1
输出:9
解释:选出的子集是第一项,第三项和第五项。

示例2:

输入:values = [5,4,3,2,1], labels = [1,3,3,3,2], num_wanted = 3, use_limit = 2
输出:12
解释:选出的子集是第一项,第二项和第三项。

示例3:

输入:values = [9,8,8,7,6], labels = [0,0,0,1,1], num_wanted = 3, use_limit = 1
输出:16
解释:选出的子集是第一项和第四项。

示例4:

输入:values = [9,8,8,7,6], labels = [0,0,0,1,1], num_wanted = 3, use_limit = 2
输出:24
解释:选出的子集是第一项,第二项和第四项。

提示:

  1. 1 <= values.length == labels.length <= 20000
  2. 0 <= values[i], labels[i] <= 20000
  3. 1 <= num_wanted, use_limit <= values.length

解题思路

本题题目可能会有点难以理解,可用把题目中的看做带有值的标签。而labels就是标签列表,values就是标签列表对应的标签值列表。

简单点说,标签与标签值的关系为多对多,一个标签可以有多个标签值,而一个相同的值可以多个标签都使用。

而题目的意思就是在所有项中选取num_wanted个元素,但是选取的元素如果存在标签一致的情况,只能存在use_limit个相同标签的项。找出满足上述条件的子集,且该子集的项的标签值之和最大,并返回该最大值。

下面我以示例4作为例子,讲解一下我的解题思路:

输入:values = [9,8,8,7,6], labels = [0,0,0,1,1], num_wanted = 3, use_limit = 2
输出:24
解释:选出的子集是第一项,第二项和第四项。
  1. valueslabels转化为以valueskey,每个key对应多个label的结构,同时以key从大到小进行排序。内容如下所示

    9 : [0]
    8 : [0,0]
    7 : [1]
    6 : [1]
  2. 依次遍历第1步中的数据并进行处理,处理步骤如下:

    1. 遍历key对应的label列表
    2. 如果该label使用次数小于use_limit,则将将最大值加上对应的key,同时num_wanted自减
    3. 每轮循环都要判断num_wanted是否为0

实现代码

    /**
     * 1090. 受标签影响的最大值
     * @param values 标签值列表
     * @param labels 标签名列表
     * @param num_wanted 期待的标签个数
     * @param use_limit 每个标签可重复的次数
     * @return
     */
    public int largestValsFromLabels(int[] values, int[] labels, int num_wanted, int use_limit) {
        // value和label的映射,需要注意使用的是入参values作为key倒序(从大到小)存储
        Map<Integer, List<Integer>> valueLabelMap = new TreeMap<>(Comparator.reverseOrder());
        // 每个label的出现次数
        Map<Integer,Integer> occurTimes = new HashMap<>();
        // 最大值
        int result = 0;
        for(int i=0;i<labels.length;i++){ // 转成value和label的映射
            if(valueLabelMap.containsKey(values[i])){
                valueLabelMap.get(values[i]).add(labels[i]);
            }else{
                List<Integer> list=new ArrayList<>();
                list.add(labels[i]);
                valueLabelMap.put(values[i],list);
            }
        }
        Iterator<Map.Entry<Integer,List<Integer>>> it=valueLabelMap.entrySet().iterator();
        while (it.hasNext()){ // 遍历TreeMap
            Map.Entry<Integer,List<Integer>> entry = it.next();
            // 对应的值
            Integer value = entry.getKey();
            List<Integer> labelList = entry.getValue();
            labelList.sort(Comparator.comparing(Integer::intValue));
            for(int i=0;i<labelList.size();i++){ // 遍历label列表
                Integer label=labelList.get(i);
                if(occurTimes.containsKey(label)){ // label是否被使用过
                    if(occurTimes.get(label)<use_limit){ // 是否超出使用上限
                        result+=value;
                        occurTimes.put(label,occurTimes.get(label)+1);
                        --num_wanted; // 减少可用个数
                    }
                }else{
                    occurTimes.put(label,1);
                    result+=value;
                    --num_wanted; // 减少可用个数
                }
                if(num_wanted==0){ // 可用个数为0,中断循环
                    break;
                }
            }
            if(num_wanted==0){
                break;
            }
        }
        return result;
    }

Null
137 声望31 粉丝

免费的东西是最贵的,好走的只是下坡路


« 上一篇
1089-复写零