Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e249ecb

Browse files
authored
feat: add solutions to lc problem: No.2910 (doocs#1871)
No.2910.Minimum Number of Groups to Create a Valid Assignment
1 parent 11f9d06 commit e249ecb

File tree

8 files changed

+481
-6
lines changed

8 files changed

+481
-6
lines changed

solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md

Lines changed: 166 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,34 +64,197 @@
6464

6565
<!-- 这里可写通用的实现逻辑 -->
6666

67+
**方法一:哈希表 + 枚举**
68+
69+
我们用一个哈希表 $cnt$ 统计数组 $nums$ 中每个数字出现的次数,我们记数字次数的最小值为 $k$,那么我们可以在 $[k,..1]$ 的范围内枚举分组的大小。由于每个组的大小差值不超过 $1$,那么分组大小为 $k$ 或 $k+1$。
70+
71+
对于当前枚举到的分组大小 $k$,我们遍历哈希表中的每个次数 $v$,如果 $\lfloor \frac{v}{k} \rfloor < v \bmod k$,那么说明无法将这个次数 $v$ 分成 $k$ 个或 $k+1$ 个数值相同的组,因此我们可以直接跳过这个分组大小 $k$。否则,说明可以分组,我们只需要尽可能分出最多的分组大小 $k+1$,即可保证得到最小的分组数,因此我们可以将 $v$ 个数分成 $\lceil \frac{v}{k+1} \rceil$ 组,累加到当前枚举的答案中。由于我们是按照 $k$ 从大到小枚举的,因此只要找到了一个合法的分组方案,那么一定是最优的。
72+
73+
时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。
74+
6775
<!-- tabs:start -->
6876

6977
### **Python3**
7078

7179
<!-- 这里可写当前语言的特殊实现逻辑 -->
7280

7381
```python
74-
82+
class Solution:
83+
def minGroupsForValidAssignment(self, nums: List[int]) -> int:
84+
cnt = Counter(nums)
85+
for k in range(min(cnt.values()), 0, -1):
86+
ans = 0
87+
for v in cnt.values():
88+
if v // k < v % k:
89+
ans = 0
90+
break
91+
ans += (v + k) // (k + 1)
92+
if ans:
93+
return ans
7594
```
7695

7796
### **Java**
7897

7998
<!-- 这里可写当前语言的特殊实现逻辑 -->
8099

81100
```java
82-
101+
class Solution {
102+
public int minGroupsForValidAssignment(int[] nums) {
103+
Map<Integer, Integer> cnt = new HashMap<>();
104+
for (int x : nums) {
105+
cnt.merge(x, 1, Integer::sum);
106+
}
107+
int k = nums.length;
108+
for (int v : cnt.values()) {
109+
k = Math.min(k, v);
110+
}
111+
for (;; --k) {
112+
int ans = 0;
113+
for (int v : cnt.values()) {
114+
if (v / k < v % k) {
115+
ans = 0;
116+
break;
117+
}
118+
ans += (v + k) / (k + 1);
119+
}
120+
if (ans > 0) {
121+
return ans;
122+
}
123+
}
124+
}
125+
}
83126
```
84127

85128
### **C++**
86129

87130
```cpp
88-
131+
class Solution {
132+
public:
133+
int minGroupsForValidAssignment(vector<int>& nums) {
134+
unordered_map<int, int> cnt;
135+
for (int x : nums) {
136+
cnt[x]++;
137+
}
138+
int k = 1e9;
139+
for (auto& [_, v] : cnt) {
140+
ans = min(ans, v);
141+
}
142+
for (;; --k) {
143+
int ans = 0;
144+
for (auto& [_, v] : cnt) {
145+
if (v / k < v % k) {
146+
ans = 0;
147+
break;
148+
}
149+
ans += (v + k) / (k + 1);
150+
}
151+
if (ans) {
152+
return ans;
153+
}
154+
}
155+
}
156+
};
89157
```
90158
91159
### **Go**
92160
93161
```go
162+
func minGroupsForValidAssignment(nums []int) int {
163+
cnt := map[int]int{}
164+
for _, x := range nums {
165+
cnt[x]++
166+
}
167+
k := len(nums)
168+
for _, v := range cnt {
169+
k = min(k, v)
170+
}
171+
for ; ; k-- {
172+
ans := 0
173+
for _, v := range cnt {
174+
if v/k < v%k {
175+
ans = 0
176+
break
177+
}
178+
ans += (v + k) / (k + 1)
179+
}
180+
if ans > 0 {
181+
return ans
182+
}
183+
}
184+
}
185+
186+
func min(a, b int) int {
187+
if a < b {
188+
return a
189+
}
190+
return b
191+
}
192+
```
193+
194+
### **TypeScript**
195+
196+
```ts
197+
function minGroupsForValidAssignment(nums: number[]): number {
198+
const cnt: Map<number, number> = new Map();
199+
for (const x of nums) {
200+
cnt.set(x, (cnt.get(x) || 0) + 1);
201+
}
202+
for (let k = Math.min(...cnt.values()); ; --k) {
203+
let ans = 0;
204+
for (const [_, v] of cnt) {
205+
if (((v / k) | 0) < v % k) {
206+
ans = 0;
207+
break;
208+
}
209+
ans += Math.ceil(v / (k + 1));
210+
}
211+
if (ans) {
212+
return ans;
213+
}
214+
}
215+
}
216+
```
217+
218+
### **Rust**
219+
220+
```rust
221+
use std::collections::HashMap;
222+
223+
impl Solution {
224+
pub fn min_groups_for_valid_assignment(nums: Vec<i32>) -> i32 {
225+
let mut cnt: HashMap<i32, i32> = HashMap::new();
226+
227+
for x in nums.iter() {
228+
let count = cnt.entry(*x).or_insert(0);
229+
*count += 1;
230+
}
231+
232+
let mut k = i32::MAX;
233+
234+
for &v in cnt.values() {
235+
k = k.min(v);
236+
}
237+
238+
for k in (1..=k).rev() {
239+
let mut ans = 0;
240+
241+
for &v in cnt.values() {
242+
if v / k < v % k {
243+
ans = 0;
244+
break;
245+
}
246+
247+
ans += (v + k) / (k + 1);
248+
}
249+
250+
if ans > 0 {
251+
return ans;
252+
}
253+
}
94254

255+
0
256+
}
257+
}
95258
```
96259

97260
### **...**

solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md

Lines changed: 166 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,30 +58,193 @@ Hence, the answer is 4.</pre>
5858

5959
## Solutions
6060

61+
**Solution 1: Hash Table + Enumeration**
62+
63+
We use a hash table $cnt$ to count the number of occurrences of each number in the array $nums$. Let $k$ be the minimum value of the number of occurrences, and then we can enumerate the size of the groups in the range $[k,..1]$. Since the difference in size between each group is not more than $1$, the group size can be either $k$ or $k+1$.
64+
65+
For the current group size $k$ being enumerated, we traverse each occurrence $v$ in the hash table. If $\lfloor \frac{v}{k} \rfloor < v \bmod k$, it means that we cannot divide the occurrence $v$ into $k$ or $k+1$ groups with the same value, so we can skip this group size $k$ directly. Otherwise, it means that we can form groups, and we only need to form as many groups of size $k+1$ as possible to ensure the minimum number of groups. Therefore, we can divide $v$ numbers into $\lceil \frac{v}{k+1} \rceil$ groups and add them to the current enumerated answer. Since we enumerate $k$ from large to small, as long as we find a valid grouping scheme, it must be optimal.
66+
67+
The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $nums$.
68+
6169
<!-- tabs:start -->
6270

6371
### **Python3**
6472

6573
```python
66-
74+
class Solution:
75+
def minGroupsForValidAssignment(self, nums: List[int]) -> int:
76+
cnt = Counter(nums)
77+
for k in range(min(cnt.values()), 0, -1):
78+
ans = 0
79+
for v in cnt.values():
80+
if v // k < v % k:
81+
ans = 0
82+
break
83+
ans += (v + k) // (k + 1)
84+
if ans:
85+
return ans
6786
```
6887

6988
### **Java**
7089

7190
```java
72-
91+
class Solution {
92+
public int minGroupsForValidAssignment(int[] nums) {
93+
Map<Integer, Integer> cnt = new HashMap<>();
94+
for (int x : nums) {
95+
cnt.merge(x, 1, Integer::sum);
96+
}
97+
int k = nums.length;
98+
for (int v : cnt.values()) {
99+
k = Math.min(k, v);
100+
}
101+
for (;; --k) {
102+
int ans = 0;
103+
for (int v : cnt.values()) {
104+
if (v / k < v % k) {
105+
ans = 0;
106+
break;
107+
}
108+
ans += (v + k) / (k + 1);
109+
}
110+
if (ans > 0) {
111+
return ans;
112+
}
113+
}
114+
}
115+
}
73116
```
74117

75118
### **C++**
76119

77120
```cpp
78-
121+
class Solution {
122+
public:
123+
int minGroupsForValidAssignment(vector<int>& nums) {
124+
unordered_map<int, int> cnt;
125+
for (int x : nums) {
126+
cnt[x]++;
127+
}
128+
int k = 1e9;
129+
for (auto& [_, v] : cnt) {
130+
ans = min(ans, v);
131+
}
132+
for (;; --k) {
133+
int ans = 0;
134+
for (auto& [_, v] : cnt) {
135+
if (v / k < v % k) {
136+
ans = 0;
137+
break;
138+
}
139+
ans += (v + k) / (k + 1);
140+
}
141+
if (ans) {
142+
return ans;
143+
}
144+
}
145+
}
146+
};
79147
```
80148
81149
### **Go**
82150
83151
```go
152+
func minGroupsForValidAssignment(nums []int) int {
153+
cnt := map[int]int{}
154+
for _, x := range nums {
155+
cnt[x]++
156+
}
157+
k := len(nums)
158+
for _, v := range cnt {
159+
k = min(k, v)
160+
}
161+
for ; ; k-- {
162+
ans := 0
163+
for _, v := range cnt {
164+
if v/k < v%k {
165+
ans = 0
166+
break
167+
}
168+
ans += (v + k) / (k + 1)
169+
}
170+
if ans > 0 {
171+
return ans
172+
}
173+
}
174+
}
175+
176+
func min(a, b int) int {
177+
if a < b {
178+
return a
179+
}
180+
return b
181+
}
182+
```
183+
184+
### **TypeScript**
185+
186+
```ts
187+
function minGroupsForValidAssignment(nums: number[]): number {
188+
const cnt: Map<number, number> = new Map();
189+
for (const x of nums) {
190+
cnt.set(x, (cnt.get(x) || 0) + 1);
191+
}
192+
for (let k = Math.min(...cnt.values()); ; --k) {
193+
let ans = 0;
194+
for (const [_, v] of cnt) {
195+
if (((v / k) | 0) < v % k) {
196+
ans = 0;
197+
break;
198+
}
199+
ans += Math.ceil(v / (k + 1));
200+
}
201+
if (ans) {
202+
return ans;
203+
}
204+
}
205+
}
206+
```
207+
208+
### **Rust**
209+
210+
```rust
211+
use std::collections::HashMap;
212+
213+
impl Solution {
214+
pub fn min_groups_for_valid_assignment(nums: Vec<i32>) -> i32 {
215+
let mut cnt: HashMap<i32, i32> = HashMap::new();
216+
217+
for x in nums.iter() {
218+
let count = cnt.entry(*x).or_insert(0);
219+
*count += 1;
220+
}
221+
222+
let mut k = i32::MAX;
223+
224+
for &v in cnt.values() {
225+
k = k.min(v);
226+
}
227+
228+
for k in (1..=k).rev() {
229+
let mut ans = 0;
230+
231+
for &v in cnt.values() {
232+
if v / k < v % k {
233+
ans = 0;
234+
break;
235+
}
236+
237+
ans += (v + k) / (k + 1);
238+
}
239+
240+
if ans > 0 {
241+
return ans;
242+
}
243+
}
84244

245+
0
246+
}
247+
}
85248
```
86249

87250
### **...**

0 commit comments

Comments
 (0)