leetcode_2910 合法分组的最少组数

1. 题意

给定一组数。将这些数进行分组,使得

  1. 组内所有元素相等
  2. 任意两个组的大小相差不超过1

合法分组的最少组数

2. 题解

直接引用别人的题解算了吧,是一个数学变换的题。

核心是当 ⌊ v k ⌋ ≥ v % k \lfloor \frac {v}{k} \rfloor \ge v \%k kvv%k时, v v v一定可以分为 k k k k + 1 k+1 k+1的组。

且此时分得的组数最少为 ⌈ v k + 1 ⌉ \lceil \frac{v}{k+1} \rceil k+1v

首先统计 n u m s nums nums,得到数组 a r r arr arr。题目要求找到一个分组基准 d d d,使得 a r r arr arr的每个元素可以由若干个 d d d d + 1 d+1 d+1组成。对于元素 a a a,假设 a = x d + y ( d + 1 ) a = x d + y ( d + 1 ) a = x d + y ( d + 1 ) a=xd+y(d+1)a=xd+y(d+1)a=xd+y(d+1) a=xd+y(d+1)a=xd+y(d+1)a=xd+y(d+1)满足分组条件,变形得 a = ( x + y ) d + y a = ( x + y ) d + y a = ( x + y ) d + y a=(x+y)d+ya=(x+y)d+ya=(x+y)d+y a=(x+y)d+ya=(x+y)d+ya=(x+y)d+y。另设 a = p d + r a=pd+r a=pd+r,其中 p = a / / d , r = a % d p=a//d,r=a\%d p=a//d,r=a%d。则 a a a可以写成 a = ( p − k ) d + ( k d + r ) a=(p−k)d+(kd+r) a=(pk)d+(kd+r)。式子联立得 p − k = x + y ≥ y = k d + r p−k=x+y≥y=kd+r pk=x+yy=kd+r,因此满足分组条件的充要条件是 p − k ≥ k d + r p−k≥kd+r pkkd+r。注意到当 k = 0 k=0 k=0时, p − k p−k pk最大, k d + r kd+r kd+r最小。因此只需要 p ≥ r p≥r pr即可满足分组条件。
要求的最优解是 x + y = p − k x+y=p−k x+y=pk的最小值。由 p − k ≥ k d + r p−k≥kd+r pkkd+r k ≤ ( p − r ) / / ( d + 1 ) k≤(p−r)//(d+1) k(pr)//(d+1),因此最优解为 p − ( ( p − r ) / / ( d + 1 ) ) p− ((p−r)//(d+1)) p((pr)//(d+1))

  • 代码
class Solution {
public:



    int minGroupsForValidAssignment(vector<int>& nums) {
        

        // 3 2 3 2 3
        // 333 22 

        // 10 10 10 3 1 1
        // 11 1010 10 3

        unordered_map<int,int> um;
        for (auto &v : nums)
            um[v]++;
        vector<int> g;
        for (auto &[k, v]: um)
            g.push_back(v);
        
        sort(g.begin(), g.end() );

        int ans = 0;
        for (int d = g[0]; d >  0; --d) {
            
            ans = 0;
            for ( auto &v: g) {

                int r = v % d ;
                if ( v / d < r) {
                    ans = 0; break;
                }
                
                ans += (v + d)/(d + 1); 
            
            }
            if (ans)
                break;
        }



        return ans;
    }
};

3. 引用

03xf
云飘飘
Jacky

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值