森林中的兔子

标签: 贪心 数组 哈希表 数学

难度: Medium

森林中有未知数量的兔子。提问其中若干只兔子 "还有多少只兔子与你(指被提问的兔子)颜色相同?" ,将答案收集到一个整数数组 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

Submission

运行时间: 24 ms

内存: 16.2 MB

class Solution:
    def numRabbits(self, answers: List[int]) -> int:
        count = {}
        for ans in answers:
            count[ans] = count.get(ans, 0) + 1
    
        min_rabbits = 0
        for ans, freq in count.items():
            min_rabbits += (freq + ans) // (ans + 1) * (ans + 1)
    
        return min_rabbits

Explain

这个题解采用了哈希表来统计每个回答出现的频率。然后,对于每个回答,计算至少需要多少只兔子可以得到这个回答。如果一个回答是x,那么至少需要x+1只兔子有相同的颜色,这样其中一只兔子回答x就是合理的。如果有多于x+1只兔子给出了相同的回答x,那么就需要额外的兔子来满足这些回答,这就需要将兔子分成不同的颜色组,每组x+1只兔子。最后,将所有需要的兔子数量相加,就得到了森林中兔子的最少数量。

时间复杂度: O(n)

空间复杂度: O(n)

class Solution:
    def numRabbits(self, answers: List[int]) -> int:
        count = {}  # 创建哈希表来统计每个回答的频率
        for ans in answers:
            count[ans] = count.get(ans, 0) + 1  # 更新哈希表

        min_rabbits = 0
        for ans, freq in count.items():
            min_rabbits += (freq + ans) // (ans + 1) * (ans + 1)  # 计算最少兔子数量

        return min_rabbits  # 返回结果

Explore

为了准确计算需要分成几组,我们先计算每个回答x的频率freq。假设有freq只兔子回答x,那么每组至少需要x+1只兔子。将freq除以x+1可以得到完整组的数量,如果有余数,说明还需要额外一组来容纳剩余的兔子。因此,总的组数是(freq + x) // (x + 1),这里使用的是整数除法,它能正确地向上取整处理有余数的情况。

这个公式目的是计算在给出相同回答ans的freq只兔子中,最小可能存在的兔子总数。首先,(freq + ans) // (ans + 1) 计算出需要的完整组数,这确保了每组都有ans+1只兔子,而且能包括所有给出这种回答的兔子。然后,乘以(ans + 1) 是为了得到这些组中兔子的总数。这种计算方法确保了兔子数量的最小化,同时满足题目条件,即每组中至少有一只兔子会回答ans,并且组内所有兔子颜色相同。

使用哈希表统计回答频率通常在算法性能上很有效,因为更新和查询操作的平均时间复杂度为O(1)。在极端情况下,如所有回答都相同,哈希表只有一个键值对,这对算法性能几乎没有影响,因为处理的时间复杂度仍然是O(n),n是回答的数量。如果每个回答都不同,则哈希表将有n个键值对,尽管键值对数量增加了,但由于哈希表的高效性,整体性能仍然保持在O(n)。因此,这些极端情况不会显著影响算法的性能。

题解的假设基于最小化总兔子数量的目的。如果实际中相同回答的兔子颜色可能不同,则可能需要更多的兔子。这种情况下,算法可能低估实际的兔子数量。然而,在没有额外信息的情况下(例如,不知道具体哪些兔子颜色可能不同),题解的方法提供了一个合理的最小估计。如果需要考虑颜色不同的情况,我们可能需要有关兔子颜色分布的额外数据才能更准确地估计。