点击获取AI摘要

781. 森林中的兔子 M

森林中有未知数量的兔子。提问其中若干只兔子 “还有多少只兔子与你(指被提问的兔子)颜色相同?” ,将答案收集到一个整数数组 answers 中,其中 answers[i] 是第 i 只兔子的回答。

给你数组 answers ,返回森林中兔子的最少数量。

示例 1:

输入:answers = [1,1,2]
输出:5
解释
两只回答了 “1” 的兔子可能有相同的颜色,设为红色。
之后回答了 “2” 的兔子不会是红色,否则他们的回答会相互矛盾。
设回答了 “2” 的兔子为蓝色。
此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。
因此森林中兔子的最少数量是 5 只:3 只回答的和 2 只没有回答的。

示例 2:

输入:answers = [10,10,10]
输出:11

提示:

  • 1 <= answers.length <= 1000
  • 0 <= answers[i] < 1000

问题分析

我们需要根据兔子的回答 answers 数组计算森林中最少的兔子数量。每只回答为 a 的兔子表示其颜色族群中有 a + 1 只兔子(包括自己)。关键在于将相同答案的兔子尽可能分到同一族群,以最小化总数。

算法思路

  1. 遍历 answers 数组,使用哈希表 count 统计每个回答值 x 出现的频次 c

  2. 对于每个不同的 x

    • 每组最多能容纳 x+1 只兔子;

    • 如果有 c 只兔子都回答了 x,则需要的组数为:

      groups=cx+1\text{groups} = \left\lceil \frac{c}{x+1} \right\rceil

    • 每个族群贡献 x + 1 只兔子,这些组中总兔子数为:

      groups×(x+1)\text{groups} \times (x+1)

  3. 将所有不同回答值对应的最少兔子数累加,即可得到森林中兔子的最少数量。

时间复杂度

  • 统计频率的时间复杂度:O(n)O(n),其中数组长度 n=answers.lengthn=answers.length ,因为仅需一次遍历统计,再对哈希表键值进行遍历。
  • 分组计算的时间复杂度:O(m)O(m),其中 mm 是不同答案的个数 (mn)(m ≤ n)。因此总时间复杂度为 O(n)O(n)
  • 空间复杂度:O(m)O(m),其中 mm 是不同回答值的数量,最坏情况 m=nm = n

代码分解

  1. 统计答案频率:使用 collections.Counter 记录每个回答的出现次数。
  2. 分组计算
    • 对于每个回答x和对应的计数c
      • 分组数目为 (c + x) // (x + 1)(使用整数运算 (c + group_size - 1) // group_size 来替代向上取整)。
      • 总兔子数累加 groups * (x + 1)

代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from collections import Counter
from typing import List

class Solution:
def numRabbits(self, answers: List[int]) -> int:
count = Counter(answers)
total = 0
for x, c in count.items():
# 每组容量为 x+1
group_size = x + 1
# 计算需要的最少族群数量(ceil(c / group_size)向上取整)
groups = (c + group_size - 1) // group_size
# 累加该回答值对应的最少兔子数
total += groups * group_size
return total