[LeetCode] 每日一题 781. 森林中的兔子(贪心 + 计数)
题目描述
森林中有未知数量的兔子。提问其中若干只兔子 "还有多少只兔子与你(指被提问的兔子)颜色相同?" ,将答案收集到一个整数数组 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
解题思路
这道题属于典型的贪心 + 计数类问题,题目要求我们根据若干只兔子的回答,推测森林中兔子的最少数量。
每只兔子的回答是:还有多少只兔子和它颜色相同。例如,如果某只兔子回答 2
,意味着它知道还有 2 只兔子和它颜色相同,它们组成了一个大小为 3 的同色兔子群体(它自己加上回答的数量)。
那我们的问题就转化成了:如何用这些回答去拼出森林中最少的兔子数量?
贪心思路
如果我们看到有很多兔子都回答 2
,我们自然倾向于把这些兔子尽可能多地归入同一个颜色组(这样可以减少总的兔子数量)。
更具体地说:
如果有
cnt
只兔子都回答了y
;那我们最多每
(y + 1)
个兔子分为一组,表示一组颜色;需要的组数是
ceil(cnt / (y + 1))
;每组都要补齐成
y + 1
个兔子,所以兔子总数为:ceil(cnt / (y + 1)) * (y + 1)
代码实现
class Solution {
public int numRabbits(int[] answers) {
HashMap<Integer, Integer> count = new HashMap<>();
for (int answer : answers) {
count.put(answer, count.getOrDefault(answer, 0) + 1);
}
int ans = 0;
for (Integer key : count.keySet()) {
int cnt = count.get(key);
ans += (cnt + key) / (key + 1) * (key + 1);
}
return ans;
}
}
复杂度分析
时间复杂度:O(n) 🚀
遍历一次answers
数组,之后遍历哈希表中的 key,都是线性操作空间复杂度:O(n) 🧠
最坏情况下,每只兔子的回答都不同,需要一个长度为 n 的哈希表
总结
这题的本质是抽象建模 + 贪心分组。关键在于理解每一个回答实际上在定义一个颜色组的大小,而题目让我们以最节省的方式进行分组。这种题目非常适合培养我们对“最值问题”的贪心直觉 💡
希望这篇分享能为你带来启发!如果你有任何问题或建议,欢迎在评论区留言,与我共同交流探讨。