F*ck Leetcode medium 1090. Largest Values From Labels

題幹:https://leetcode.com/problems/largest-values-from-labels/

 

本體可以看成是揹包問題的進階版,目標類似,是讓value最大化,不過有兩個約束條件,一是選取綜述不超過num_wanted, 二是選出的子集如果用label分組的話,每組的元素數量不超過use_limit。

思路大概如下:先把value值分組,並對每組內元素從大到小排序,然後組間按照第一個元素排序(從大到小)。

排序號每次摘取第一個組的第一個元素,即爲整體最大元素,這樣摘取num_wanted次,或者到無元素可摘的情況,每次摘取還要注意每組摘取的數量不得超過use_limit個,爲了更方便地實現這一點,可以在分組時就實現吧每組的元素限制在use_limit個,超過的就直接丟棄,因爲反正也選不上。

 

這裏的方法其實屬於貪心法,其實嚴格來說,這裏需要證明的爲什麼本處貪心法是work的,是能達到全局最優的,因爲這裏是個簡答求最大值問題,所以證明不會特別複雜,我這裏略過了。

 

代碼如下:

package com.example.demo.leetcode;

import java.util.*;

public class LargestValuesFromLabels {
    public int largestValsFromLabels(int[] values, int[] labels, int num_wanted, int use_limit) {

        Map<Integer, List<Integer>> label2values = new HashMap<>();
        for(int i=0;i<labels.length;i++){
            add2map(label2values, labels[i], values[i], use_limit);
        }

        List<List<Integer>> sortedList = new ArrayList<>();

        for(Map.Entry<Integer, List<Integer>> entry : label2values.entrySet()){
            //就是爲了收集排好序的分組,按照每組第一個元素的大小,從大到小排列
            sortedList.add(entry.getValue());
        }

        Comparator<List<Integer>> comp = new Comparator<List<Integer>>(){
            @Override
            public int compare(List<Integer> s1, List<Integer> s2) {
                if(s2.get(0)>s1.get(0)){
                    return 1;
                }else if(s2.get(0).equals(s1.get(0))){
                    return 0;
                }else if(s2.get(0)<s1.get(0)){
                    return -1;
                }
                return -1000;
            }
        };

        Collections.sort(sortedList, comp);
        int sum = 0;
        for(int i=0;i<num_wanted;i++){
            if(sortedList.size()<1){
                break;
            }
            List<Integer> k = sortedList.get(0);
            if(k.size()>0){
                sum+=k.get(0);
                sortedList.remove(0);
                k.remove(0);
                if(k.size()>0){
                    sortedList.add(k);
                }
                Collections.sort(sortedList, comp);
            }
        }
        return sum;
    }

    private void add2map(Map<Integer, List<Integer>> mp, Integer key, Integer val, int longest){
        if(mp.get(key)!=null){
            List<Integer> list = mp.get(key);

            int i=0;
            while(i<list.size() && list.get(i)>val){
                i++;
            }

            list.add(i, val);

            if(list.size()>longest){
                list.remove(list.size()-1);
            }
        }else{
            List<Integer> eIndexs = new ArrayList<>();
            eIndexs.add(val);
            mp.put(key, eIndexs);
        }
    }


    public static void main(String[] args) {

        LargestValuesFromLabels demo = new LargestValuesFromLabels();

//        int[] values = {5,4,3,2,1};
//        int[] values = {9,8,8,7,6};
        int[] values = {3,2,3,2,1};
//        int[] values = {5963,15066,7870,4883,18205,19694,1938,2291,13915,16317,12347,19514,2766,13578,18721,892,1683,12691,6700,17793,19514,10687,8106,11006,11841,5992,602,7538,13220,15178,14142,7813,17632,16438,3652,9630,19297,19328,12118,18871,1024,10888,2668,6695,6990,8680,13515,10150,6218,18402};
//        int[] labels = {0,0,0,1,1};
        int[] labels = {1,0,2,2,1};
//        int[] labels = {1,1,2,2,3};
//        int[] labels = {7149,19554,17254,15626,5710,9132,9068,1432,14982,3596,12403,1746,10231,11836,449,15140,17696,17094,795,4355,1227,5973,18464,6046,10232,5538,10066,14692,18832,11861,7265,13952,9448,6164,14014,8073,13446,18649,18769,6285,13127,2109,13319,10794,9828,15545,12451,11604,4072,9114};
//        int num_wanted = 3;
        int num_wanted = 2;
        int use_limit = 1;
        int ret = demo.largestValsFromLabels(values, labels, num_wanted, use_limit);

        System.out.println(ret);
    }

}

 

反思: 一開始沒有想到用貪心法,導致嘗試用動態規劃做了很久,到頭來卻是OJ不停地報timeout,心力憔悴,還是不能一招動態規劃打天下啊。。。理論聯繫實際一下,扒動態規劃和貪心的關係: https://labuladong.gitbook.io/algo/dong-tai-gui-hua-xi-lie/tan-xin-suan-fa-zhi-qu-jian-tiao-du-wen-ti

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章