牛客编程巅峰赛S1第11场 - 黄金&钻石 C.牛牛找子集

牛客编程巅峰赛S1第11场 - 黄金&钻石 C.牛牛找子集

题目链接

题目描述

牛牛和牛妹在玩一个游戏,在他们面前有n个数。牛妹说出一个数字k,牛牛就要从这些数中找到多个由k个数字组成的子集,每个数字有且只能使用一次,并且这些子集是完全相同的,子集内部元素可以相同,完全相同的子集是指两个集合里的元素及其个数都是相同的。
游戏胜利的目标是:找到满足游戏规则,且数量最多的子集。
牛牛特别想赢得游戏,所以他想请你帮他写一个程序,找到能够满足游戏胜利条件的子集,并且输出这个子集。如果有多个子集满足条件,输出字典序最小的即可。

示例1

输入

12,5,[1,1,1,1,1,1,2,2,2,2,2,2]

输出

[1,1,1,2,2]

示例2

输入

7,3,[1,2,3,2,4,3,1]

输出

[1,2,3]

白给题,我二分真的差,总是忽略这种做法,这题就是裸的二分,找能分的最大组数,然后按最大组数挑数输出即可,注意挑出来的数的数量可能大于 k k k,所以最后要 r e s i z e resize resize 一下,样例一就是一个特例,AC代码如下:

class Solution {
public:
    /**
     * 返回找到能够满足游戏胜利条件的子集,如果有多个子集满足条件,返回字典序最小的即可。
     * @param n int整型 代表数字的数量
     * @param k int整型 代表子集的大小
     * @param s int整型vector 代表数字数组
     * @return int整型vector
     */
    vector<int> solve(int n, int k, vector<int> &s){
        vector<int>ans;
        map<int,int>mp;
        for(auto i:s) mp[i]++;
        int l=1,r=n;
        while(l<=r){
            int mid=l+r>>1,siz=0;
            for(auto i:mp){
                siz+=i.second/mid;
            }
            if(siz>=k) l=mid+1;
            else r=mid-1;
        }
        for(auto i:mp){
            for(int j=0;j<i.second/r;j++) ans.push_back(i.first);
        }
        ans.resize(k);
        return ans;
    }
};

你可能感兴趣的:(二分,牛客)