|
| 1 | +--- |
| 2 | +title: 781.森林中的兔子:思维题(哈希表+贪心) —— 通俗易懂讲解版 |
| 3 | +date: 2025-04-20 21:15:13 |
| 4 | +tags: [题解, LeetCode, 中等, 贪心, 数组, 哈希表, map, 数学] |
| 5 | +categories: [题解, LeetCode] |
| 6 | +--- |
| 7 | + |
| 8 | +# 【LetMeFly】781.森林中的兔子:思维题(哈希表+贪心) —— 通俗易懂讲解版 |
| 9 | + |
| 10 | +力扣题目链接:[https://leetcode.cn/problems/rabbits-in-forest/](https://leetcode.cn/problems/rabbits-in-forest/) |
| 11 | + |
| 12 | +<p>森林中有未知数量的兔子。提问其中若干只兔子<strong> "还有多少只兔子与你(指被提问的兔子)颜色相同?"</strong> ,将答案收集到一个整数数组 <code>answers</code> 中,其中 <code>answers[i]</code> 是第 <code>i</code> 只兔子的回答。</p> |
| 13 | + |
| 14 | +<p>给你数组 <code>answers</code> ,返回森林中兔子的最少数量。</p> |
| 15 | + |
| 16 | +<p> </p> |
| 17 | + |
| 18 | +<p><strong>示例 1:</strong></p> |
| 19 | + |
| 20 | +<pre> |
| 21 | +<strong>输入:</strong>answers = [1,1,2] |
| 22 | +<strong>输出:</strong>5 |
| 23 | +<strong>解释:</strong> |
| 24 | +两只回答了 "1" 的兔子可能有相同的颜色,设为红色。 |
| 25 | +之后回答了 "2" 的兔子不会是红色,否则他们的回答会相互矛盾。 |
| 26 | +设回答了 "2" 的兔子为蓝色。 |
| 27 | +此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。 |
| 28 | +因此森林中兔子的最少数量是 5 只:3 只回答的和 2 只没有回答的。 |
| 29 | +</pre> |
| 30 | + |
| 31 | +<p><strong>示例 2:</strong></p> |
| 32 | + |
| 33 | +<pre> |
| 34 | +<strong>输入:</strong>answers = [10,10,10] |
| 35 | +<strong>输出:</strong>11 |
| 36 | +</pre> |
| 37 | + |
| 38 | +<p> </p> |
| 39 | + |
| 40 | +<p><strong>提示:</strong></p> |
| 41 | + |
| 42 | +<ul> |
| 43 | + <li><code>1 <= answers.length <= 1000</code></li> |
| 44 | + <li><code>0 <= answers[i] < 1000</code></li> |
| 45 | +</ul> |
| 46 | + |
| 47 | +很有意思的一道题。 |
| 48 | + |
| 49 | +## 解题方法:哈希表+贪心 |
| 50 | + |
| 51 | ++ 假设有$3$只兔子的答案是“还有4只兔子和它颜色相同”,那么最少有几只兔子?最少有4只(这$3$只一组再加上没问到的一只一个色)。 |
| 52 | ++ 假设有$4$只兔子的答案是“还有4只兔子和它颜色相同”,那么最少有几只兔子?最少有4只(这$4$只一组一个色)。 |
| 53 | ++ 假设有$5$只兔子的答案是“还有4只兔子和它颜色相同”,那么最少有几只兔子?最少有8只(其中$4$只一组一个色,另外一只和其他没问到的$3$只一组另一个色)。 |
| 54 | ++ 假设有$6$只兔子的答案是“还有4只兔子和它颜色相同”,那么最少有几只兔子?最少有8只(其中$4$只一组一个色,另外两只和其他没问到的$2$只一组另一个色)。 |
| 55 | + |
| 56 | +不难发现,假设“和另外$group$只兔子颜色相同”的兔子一共有$total$只,那么这些兔子最少有多少只?最少有$\lceil\frac{total}{group + 1}\rceil\times (group+1)$只。 |
| 57 | + |
| 58 | +题外话:$\lceil\frac{total}{group + 1}\rceil\times (group+1)=\lfloor\frac{total+group}{group + 1}\rfloor\times (group+1)$。 |
| 59 | + |
| 60 | ++ 时间复杂度$O(len(answers))$ |
| 61 | ++ 空间复杂度$O(len(answers))$ |
| 62 | + |
| 63 | +### AC代码 |
| 64 | + |
| 65 | +#### C++ |
| 66 | + |
| 67 | +```cpp |
| 68 | +/* |
| 69 | + * @Author: LetMeFly |
| 70 | + * @Date: 2025-04-20 19:35:57 |
| 71 | + * @LastEditors: LetMeFly.xyz |
| 72 | + * @LastEditTime: 2025-04-20 19:40:16 |
| 73 | + */ |
| 74 | +class Solution { |
| 75 | +public: |
| 76 | + int numRabbits(vector<int>& answers) { |
| 77 | + unordered_map<int, int> times; |
| 78 | + for (int t : answers) { |
| 79 | + times[t]++; |
| 80 | + } |
| 81 | + int ans = 0; |
| 82 | + for (auto [group, total] : times) { |
| 83 | + ans += (total + group) / (group + 1) * (group + 1); |
| 84 | + } |
| 85 | + return ans; |
| 86 | + } |
| 87 | +}; |
| 88 | +``` |
| 89 | +
|
| 90 | +#### Python |
| 91 | +
|
| 92 | +```python |
| 93 | +''' |
| 94 | +Author: LetMeFly |
| 95 | +Date: 2025-04-20 19:53:58 |
| 96 | +LastEditors: LetMeFly.xyz |
| 97 | +LastEditTime: 2025-04-20 20:05:51 |
| 98 | +''' |
| 99 | +from typing import List |
| 100 | +from collections import Counter |
| 101 | +
|
| 102 | +class Solution: |
| 103 | + def numRabbits(self, answers: List[int]) -> int: |
| 104 | + return sum((group + total) // (group + 1) * (group + 1) for group, total in Counter(answers).items()) |
| 105 | +``` |
| 106 | + |
| 107 | +#### Java |
| 108 | + |
| 109 | +```java |
| 110 | +/* |
| 111 | + * @Author: LetMeFly |
| 112 | + * @Date: 2025-04-20 21:06:44 |
| 113 | + * @LastEditors: LetMeFly.xyz |
| 114 | + * @LastEditTime: 2025-04-20 21:12:27 |
| 115 | + */ |
| 116 | +import java.util.Map; |
| 117 | +import java.util.HashMap; |
| 118 | + |
| 119 | +class Solution { |
| 120 | + public int numRabbits(int[] answers) { |
| 121 | + Map<Integer, Integer> times = new HashMap<>(); |
| 122 | + for (int t : answers) { |
| 123 | + times.merge(t, 1, Integer::sum); |
| 124 | + } |
| 125 | + int ans = 0; |
| 126 | + // times.forEach((group, total) -> ans += (group + total) / (group + 1) * (group + 1)); // 不可,CE |
| 127 | + for (Map.Entry<Integer, Integer> entry : times.entrySet()) { |
| 128 | + int group = entry.getKey(); |
| 129 | + int total = entry.getValue(); |
| 130 | + ans += (group + total) / (group + 1) * (group + 1); |
| 131 | + } |
| 132 | + return ans; |
| 133 | + } |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +#### Go |
| 138 | + |
| 139 | +```go |
| 140 | +/* |
| 141 | + * @Author: LetMeFly |
| 142 | + * @Date: 2025-04-20 21:04:11 |
| 143 | + * @LastEditors: LetMeFly.xyz |
| 144 | + * @LastEditTime: 2025-04-20 21:05:23 |
| 145 | + */ |
| 146 | +package main |
| 147 | + |
| 148 | +func numRabbits(answers []int) (ans int) { |
| 149 | + times := map[int]int{} |
| 150 | + for _, v := range answers { |
| 151 | + times[v]++ |
| 152 | + } |
| 153 | + for group, total := range times { |
| 154 | + ans += (total + group) / (group + 1) * (group + 1) |
| 155 | + } |
| 156 | + return |
| 157 | +} |
| 158 | +``` |
| 159 | + |
| 160 | +> 同步发文于[CSDN](https://letmefly.blog.csdn.net/article/details/147375747)和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2025/04/20/LeetCode%200781.%E6%A3%AE%E6%9E%97%E4%B8%AD%E7%9A%84%E5%85%94%E5%AD%90/)哦~ |
| 161 | +> |
| 162 | +> 千篇源码题解[已开源](https://github.com/LetMeFly666/LeetCode) |
0 commit comments