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 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;
}
};