From 0f64cd85ef855ef67e1a386303827c1b2deaa093 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 24 Oct 2023 19:55:39 +0800 Subject: [PATCH 1/2] feat: add solutions to lc problem: No.2910 No.2910.Minimum Number of Groups to Create a Valid Assignment --- .../README.md | 161 +++++++++++++++++- .../README_EN.md | 161 +++++++++++++++++- .../Solution.cpp | 26 +++ .../Solution.go | 30 ++++ .../Solution.java | 25 +++ .../Solution.py | 12 ++ .../Solution.rs | 37 ++++ .../Solution.ts | 19 +++ 8 files changed, 465 insertions(+), 6 deletions(-) create mode 100644 solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.cpp create mode 100644 solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.go create mode 100644 solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.java create mode 100644 solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.py create mode 100644 solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.rs create mode 100644 solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.ts diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md index cc647724e1e96..9626b917a736b 100644 --- a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md @@ -71,7 +71,18 @@ ```python - +class Solution: + def minGroupsForValidAssignment(self, nums: List[int]) -> int: + cnt = Counter(nums) + for k in range(min(cnt.values()), 0, -1): + ans = 0 + for v in cnt.values(): + if v // k < v % k: + ans = 0 + break + ans += (v + k) // (k + 1) + if ans: + return ans ``` ### **Java** @@ -79,19 +90,163 @@ ```java - +class Solution { + public int minGroupsForValidAssignment(int[] nums) { + Map cnt = new HashMap<>(); + for (int x : nums) { + cnt.merge(x, 1, Integer::sum); + } + int k = nums.length; + for (int v : cnt.values()) { + k = Math.min(k, v); + } + for (;; --k) { + int ans = 0; + for (int v : cnt.values()) { + if (v / k < v % k) { + ans = 0; + break; + } + ans += (v + k) / (k + 1); + } + if (ans > 0) { + return ans; + } + } + } +} ``` ### **C++** ```cpp - +class Solution { +public: + int minGroupsForValidAssignment(vector& nums) { + unordered_map cnt; + for (int x : nums) { + cnt[x]++; + } + int k = 1e9; + for (auto& [_, v] : cnt) { + ans = min(ans, v); + } + for (;; --k) { + int ans = 0; + for (auto& [_, v] : cnt) { + if (v / k < v % k) { + ans = 0; + break; + } + ans += (v + k) / (k + 1); + } + if (ans) { + return ans; + } + } + } +}; ``` ### **Go** ```go +func minGroupsForValidAssignment(nums []int) int { + cnt := map[int]int{} + for _, x := range nums { + cnt[x]++ + } + k := len(nums) + for _, v := range cnt { + k = min(k, v) + } + for ; ; k-- { + ans := 0 + for _, v := range cnt { + if v/k < v%k { + ans = 0 + break + } + ans += (v + k) / (k + 1) + } + if ans > 0 { + return ans + } + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +### **TypeScript** + +```ts +function minGroupsForValidAssignment(nums: number[]): number { + const cnt: Map = new Map(); + for (const x of nums) { + cnt.set(x, (cnt.get(x) || 0) + 1); + } + for (let k = Math.min(...cnt.values()); ; --k) { + let ans = 0; + for (const [_, v] of cnt) { + if (((v / k) | 0) < v % k) { + ans = 0; + break; + } + ans += Math.ceil(v / (k + 1)); + } + if (ans) { + return ans; + } + } +} +``` + +### **Rust** + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn min_groups_for_valid_assignment(nums: Vec) -> i32 { + let mut cnt: HashMap = HashMap::new(); + + for x in nums.iter() { + let count = cnt.entry(*x).or_insert(0); + *count += 1; + } + + let mut k = i32::MAX; + + for &v in cnt.values() { + k = k.min(v); + } + + for k in (1..=k).rev() { + let mut ans = 0; + + for &v in cnt.values() { + if v / k < v % k { + ans = 0; + break; + } + + ans += (v + k) / (k + 1); + } + + if ans > 0 { + return ans; + } + } + 0 + } +} ``` ### **...** diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md index 1775f4087870f..c08c57ed7f5c9 100644 --- a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md @@ -63,25 +63,180 @@ Hence, the answer is 4. ### **Python3** ```python - +class Solution: + def minGroupsForValidAssignment(self, nums: List[int]) -> int: + cnt = Counter(nums) + for k in range(min(cnt.values()), 0, -1): + ans = 0 + for v in cnt.values(): + if v // k < v % k: + ans = 0 + break + ans += (v + k) // (k + 1) + if ans: + return ans ``` ### **Java** ```java - +class Solution { + public int minGroupsForValidAssignment(int[] nums) { + Map cnt = new HashMap<>(); + for (int x : nums) { + cnt.merge(x, 1, Integer::sum); + } + int k = nums.length; + for (int v : cnt.values()) { + k = Math.min(k, v); + } + for (;; --k) { + int ans = 0; + for (int v : cnt.values()) { + if (v / k < v % k) { + ans = 0; + break; + } + ans += (v + k) / (k + 1); + } + if (ans > 0) { + return ans; + } + } + } +} ``` ### **C++** ```cpp - +class Solution { +public: + int minGroupsForValidAssignment(vector& nums) { + unordered_map cnt; + for (int x : nums) { + cnt[x]++; + } + int k = 1e9; + for (auto& [_, v] : cnt) { + ans = min(ans, v); + } + for (;; --k) { + int ans = 0; + for (auto& [_, v] : cnt) { + if (v / k < v % k) { + ans = 0; + break; + } + ans += (v + k) / (k + 1); + } + if (ans) { + return ans; + } + } + } +}; ``` ### **Go** ```go +func minGroupsForValidAssignment(nums []int) int { + cnt := map[int]int{} + for _, x := range nums { + cnt[x]++ + } + k := len(nums) + for _, v := range cnt { + k = min(k, v) + } + for ; ; k-- { + ans := 0 + for _, v := range cnt { + if v/k < v%k { + ans = 0 + break + } + ans += (v + k) / (k + 1) + } + if ans > 0 { + return ans + } + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} +``` + +### **TypeScript** + +```ts +function minGroupsForValidAssignment(nums: number[]): number { + const cnt: Map = new Map(); + for (const x of nums) { + cnt.set(x, (cnt.get(x) || 0) + 1); + } + for (let k = Math.min(...cnt.values()); ; --k) { + let ans = 0; + for (const [_, v] of cnt) { + if (((v / k) | 0) < v % k) { + ans = 0; + break; + } + ans += Math.ceil(v / (k + 1)); + } + if (ans) { + return ans; + } + } +} +``` + +### **Rust** + +```rust +use std::collections::HashMap; + +impl Solution { + pub fn min_groups_for_valid_assignment(nums: Vec) -> i32 { + let mut cnt: HashMap = HashMap::new(); + + for x in nums.iter() { + let count = cnt.entry(*x).or_insert(0); + *count += 1; + } + + let mut k = i32::MAX; + + for &v in cnt.values() { + k = k.min(v); + } + + for k in (1..=k).rev() { + let mut ans = 0; + + for &v in cnt.values() { + if v / k < v % k { + ans = 0; + break; + } + + ans += (v + k) / (k + 1); + } + + if ans > 0 { + return ans; + } + } + 0 + } +} ``` ### **...** diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.cpp b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.cpp new file mode 100644 index 0000000000000..59ae0892cef2f --- /dev/null +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.cpp @@ -0,0 +1,26 @@ +class Solution { +public: + int minGroupsForValidAssignment(vector& nums) { + unordered_map cnt; + for (int x : nums) { + cnt[x]++; + } + int k = 1e9; + for (auto& [_, v] : cnt) { + ans = min(ans, v); + } + for (;; --k) { + int ans = 0; + for (auto& [_, v] : cnt) { + if (v / k < v % k) { + ans = 0; + break; + } + ans += (v + k) / (k + 1); + } + if (ans) { + return ans; + } + } + } +}; \ No newline at end of file diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.go b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.go new file mode 100644 index 0000000000000..8582ec3eaabff --- /dev/null +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.go @@ -0,0 +1,30 @@ +func minGroupsForValidAssignment(nums []int) int { + cnt := map[int]int{} + for _, x := range nums { + cnt[x]++ + } + k := len(nums) + for _, v := range cnt { + k = min(k, v) + } + for ; ; k-- { + ans := 0 + for _, v := range cnt { + if v/k < v%k { + ans = 0 + break + } + ans += (v + k) / (k + 1) + } + if ans > 0 { + return ans + } + } +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} \ No newline at end of file diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.java b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.java new file mode 100644 index 0000000000000..eaad7cd91ff05 --- /dev/null +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.java @@ -0,0 +1,25 @@ +class Solution { + public int minGroupsForValidAssignment(int[] nums) { + Map cnt = new HashMap<>(); + for (int x : nums) { + cnt.merge(x, 1, Integer::sum); + } + int k = nums.length; + for (int v : cnt.values()) { + k = Math.min(k, v); + } + for (;; --k) { + int ans = 0; + for (int v : cnt.values()) { + if (v / k < v % k) { + ans = 0; + break; + } + ans += (v + k) / (k + 1); + } + if (ans > 0) { + return ans; + } + } + } +} \ No newline at end of file diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.py b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.py new file mode 100644 index 0000000000000..94c4c4b8197c2 --- /dev/null +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.py @@ -0,0 +1,12 @@ +class Solution: + def minGroupsForValidAssignment(self, nums: List[int]) -> int: + cnt = Counter(nums) + for k in range(min(cnt.values()), 0, -1): + ans = 0 + for v in cnt.values(): + if v // k < v % k: + ans = 0 + break + ans += (v + k) // (k + 1) + if ans: + return ans diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.rs b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.rs new file mode 100644 index 0000000000000..9e7475531504d --- /dev/null +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.rs @@ -0,0 +1,37 @@ +use std::collections::HashMap; + +impl Solution { + pub fn min_groups_for_valid_assignment(nums: Vec) -> i32 { + let mut cnt: HashMap = HashMap::new(); + + for x in nums.iter() { + let count = cnt.entry(*x).or_insert(0); + *count += 1; + } + + let mut k = i32::MAX; + + for &v in cnt.values() { + k = k.min(v); + } + + for k in (1..=k).rev() { + let mut ans = 0; + + for &v in cnt.values() { + if v / k < v % k { + ans = 0; + break; + } + + ans += (v + k) / (k + 1); + } + + if ans > 0 { + return ans; + } + } + + 0 + } +} \ No newline at end of file diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.ts b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.ts new file mode 100644 index 0000000000000..506de0df770c9 --- /dev/null +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/Solution.ts @@ -0,0 +1,19 @@ +function minGroupsForValidAssignment(nums: number[]): number { + const cnt: Map = new Map(); + for (const x of nums) { + cnt.set(x, (cnt.get(x) || 0) + 1); + } + for (let k = Math.min(...cnt.values()); ; --k) { + let ans = 0; + for (const [_, v] of cnt) { + if (((v / k) | 0) < v % k) { + ans = 0; + break; + } + ans += Math.ceil(v / (k + 1)); + } + if (ans) { + return ans; + } + } +} From 6247f3a0b1685e2871c2ff7b20ad0880867c0c60 Mon Sep 17 00:00:00 2001 From: yanglbme Date: Tue, 24 Oct 2023 20:04:08 +0800 Subject: [PATCH 2/2] docs: update readme --- .../README.md | 8 ++++++++ .../README_EN.md | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md index 9626b917a736b..af96b5e299e4f 100644 --- a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README.md @@ -64,6 +64,14 @@ +**方法一:哈希表 + 枚举** + +我们用一个哈希表 $cnt$ 统计数组 $nums$ 中每个数字出现的次数,我们记数字次数的最小值为 $k$,那么我们可以在 $[k,..1]$ 的范围内枚举分组的大小。由于每个组的大小差值不超过 $1$,那么分组大小为 $k$ 或 $k+1$。 + +对于当前枚举到的分组大小 $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$ 从大到小枚举的,因此只要找到了一个合法的分组方案,那么一定是最优的。 + +时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组 $nums$ 的长度。 + ### **Python3** diff --git a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md index c08c57ed7f5c9..904acb95a0767 100644 --- a/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md +++ b/solution/2900-2999/2910.Minimum Number of Groups to Create a Valid Assignment/README_EN.md @@ -58,6 +58,14 @@ Hence, the answer is 4. ## Solutions +**Solution 1: Hash Table + Enumeration** + +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$. + +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. + +The time complexity is $O(n)$, and the space complexity is $O(n)$. Here, $n$ is the length of the array $nums$. + ### **Python3**