给你一个长度为 n
下标从 0 开始的整数数组 nums
。
我们想将下标进行分组,使得 [0, n - 1]
内所有下标 i
都 恰好 被分到其中一组。
如果以下条件成立,我们说这个分组方案是合法的:
- 对于每个组
g
,同一组内所有下标在nums
中对应的数值都相等。 - 对于任意两个组
g1
和g2
,两个组中 下标数量 的 差值不超过1
。
请你返回一个整数,表示得到一个合法分组方案的 最少 组数。
示例 1:
输入:nums = [3,2,3,2,3] 输出:2 解释:一个得到 2 个分组的方案如下,中括号内的数字都是下标: 组 1 -> [0,2,4] 组 2 -> [1,3] 所有下标都只属于一个组。 组 1 中,nums[0] == nums[2] == nums[4] ,所有下标对应的数值都相等。 组 2 中,nums[1] == nums[3] ,所有下标对应的数值都相等。 组 1 中下标数目为 3 ,组 2 中下标数目为 2 。 两者之差不超过 1 。 无法得到一个小于 2 组的答案,因为如果只有 1 组,组内所有下标对应的数值都要相等。 所以答案为 2 。
示例 2:
输入:nums = [10,10,10,3,1,1] 输出:4 解释:一个得到 2 个分组的方案如下,中括号内的数字都是下标: 组 1 -> [0] 组 2 -> [1,2] 组 3 -> [3] 组 4 -> [4,5] 分组方案满足题目要求的两个条件。 无法得到一个小于 4 组的答案。 所以答案为 4 。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 109
方法一:哈希表 + 枚举
我们用一个哈希表
对于当前枚举到的分组大小
时间复杂度
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
class Solution {
public int minGroupsForValidAssignment(int[] nums) {
Map<Integer, Integer> 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;
}
}
}
}
class Solution {
public:
int minGroupsForValidAssignment(vector<int>& nums) {
unordered_map<int, int> 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;
}
}
}
};
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
}
function minGroupsForValidAssignment(nums: number[]): number {
const cnt: Map<number, number> = 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;
}
}
}
use std::collections::HashMap;
impl Solution {
pub fn min_groups_for_valid_assignment(nums: Vec<i32>) -> i32 {
let mut cnt: HashMap<i32, i32> = 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
}
}