1. 题意
给定一组数。将这些数进行分组,使得
- 组内所有元素相等
- 任意两个组的大小相差不超过1
合法分组的最少组数
2. 题解
直接引用别人的题解算了吧,是一个数学变换的题。
核心是当 ⌊ v k ⌋ ≥ v % k \lfloor \frac {v}{k} \rfloor \ge v \%k ⌊kv⌋≥v%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=(p−k)d+(kd+r)。式子联立得 p − k = x + y ≥ y = k d + r p−k=x+y≥y=kd+r p−k=x+y≥y=kd+r,因此满足分组条件的充要条件是 p − k ≥ k d + r p−k≥kd+r p−k≥kd+r。注意到当 k = 0 k=0 k=0时, p − k p−k p−k最大, k d + r kd+r kd+r最小。因此只需要 p ≥ r p≥r p≥r即可满足分组条件。
要求的最优解是 x + y = p − k x+y=p−k x+y=p−k的最小值。由 p − k ≥ k d + r p−k≥kd+r p−k≥kd+r得 k ≤ ( p − r ) / / ( d + 1 ) k≤(p−r)//(d+1) k≤(p−r)//(d+1),因此最优解为 p − ( ( p − r ) / / ( d + 1 ) ) p− ((p−r)//(d+1)) p−((p−r)//(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 3unordered_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