In a forest, each rabbit has some color. Some subset of rabbits (possibly all of them) tell you how many other rabbits have the same color as them. Those answers are placed in an array.

Return the minimum number of rabbits that could be in the forest.

Examples:
Input: answers = [1, 1, 2]
Output: 5
Explanation:
The two rabbits that answered "1" could both be the same color, say red.
The rabbit than answered "2" can't be red or the answers would be inconsistent.
Say the rabbit that answered "2" was blue.
Then there should be 2 other blue rabbits in the forest that didn't answer into the array.
The smallest possible number of rabbits in the forest is therefore 5: 3 that answered plus 2 that didn't. Input: answers = [10, 10, 10]
Output: 11 Input: answers = []
Output: 0

Note:

  1. answers will have length at most 1000.
  2. Each answers[i] will be an integer in the range [0, 999].

这道题说的是大森林中有一堆成了精的兔子,有着不同的颜色,还会回答问题。每个兔子会告诉你森林中还有多少个和其颜色相同的兔子,当然并不是所有的兔子多出现在数组中,所以我们要根据兔子们的回答,来估计森林中最少有多少只能确定的兔子。例子1给的数字是 [1, 1, 2],第一只兔子说森林里还有另一只兔子跟其颜色一样,第二只兔子也说还有另一只兔子和其颜色一样,那么为了使兔子总数最少,我们可以让前两只兔子是相同的颜色,可以使其回答不会矛盾。第三只兔子说森林里还有两只兔子和其颜色一样,那么这只兔的颜色就不能和前两只兔子的颜色相同了,否则就会跟前面两只兔子的回答矛盾了,因为根据第三只兔子的描述,森林里共有三只这种颜色的兔子,所有总共可以推断出最少有五只兔子。对于例子2,[10, 10, 10] 来说,这三只兔子都说森林里还有10只跟其颜色相同的兔子,那么这三只兔子颜色可以相同,所以总共有11只兔子。

来看一个比较tricky的例子,[0, 0, 1, 1, 1],前两只兔子都说森林里没有兔子和其颜色相同了,那么这两只兔子就是森林里独一无二的兔子,且颜色并不相同,所以目前已经确定了两只。然后后面三只都说森林里还有一只兔子和其颜色相同,那么这三只兔子就不可能颜色都相同了,但我们可以让两只颜色相同,另外一只颜色不同,那么就是说还有一只兔子并没有在数组中,所以森林中最少有6只兔子。分析完了这几个例子,我们可以发现,如果某个兔子回答的数字是x,那么说明森林里共有x+1个相同颜色的兔子,我们最多允许x+1个兔子同时回答x个,一旦超过了x+1个兔子,那么就得再增加了x+1个新兔子了。所以我们可以使用一个HashMap来建立某种颜色兔子的总个数和在数组中还允许出现的个数之间的映射,然后我们遍历数组中的每个兔子,如果该兔子回答了x个,若该颜色兔子的总个数x+1不在HashMap中,或者映射为0了,我们将这x+1个兔子加入结果res中,然后将其映射值设为x,表示在数组中还允许出现x个也回答x的兔子;否则的话,将映射值自减1即可,参见代码如下:

解法一:

class Solution {
public:
int numRabbits(vector<int>& answers) {
int res = ;
unordered_map<int, int> m;
for (int ans : answers) {
if (!m.count(ans + ) || m[ans + ] == ) {
res += ans + ;
m[ans + ] = ans;
} else {
--m[ans + ];
}
}
return res;
}
};

下面这种方法换了个角度,核心还是当某个兔子回答x的时候,那么数组中最多允许x+1个兔子同时回答x,那么我们统计数组中所有回答x的兔子的数量n:

若 n%(x+1)==0,说明我们此时只需要 n/(x+1) 组个数为x+1的兔子。

若 n%(x+1)!=0,说明我们此时只需要 n/(x+1) + 1 组个数为x+1的兔子。

那么这两种情况可以通过 ceil(n/(x+1)) 来整合,而这个值也等于 (n + x) / (x + 1),参见代码如下:

解法二:

class Solution {
public:
int numRabbits(vector<int>& answers) {
int res = ;
unordered_map<int, int> m;
for (int ans : answers) ++m[ans];
for (auto a : m) {
res += (a.second + a.first) / (a.first + ) * (a.first + );
}
return res;
}
};

下面这种思路也很巧妙,是先统计出不在数组中的兔子的个数,然后再加上回答问题的兔子数。我们使用一个长度为1000的数字代替HashMap,因为题目中限定了最多1000个兔子回答问题,然后我们对于每个回答x的兔子,将 cnt[x] 的值自增1,然后对 x+1 取余,那么余数就是总数为 x+1 的兔子中在数组中出现的个数,所以我们之后用 x+1 减去这个余数,就是不在数组中的兔子的个数。那么你可能会怀疑,当余数为0了,会不会漏掉了兔子啊,答案是不会的,因为我们最终要加上数组中的兔子个数,如果对 x+1 取余为0了,说明这 x+1 个兔子都在数组中出现了,所以我们不会漏掉任何兔子,参见代码如下:

解法三:

class Solution {
public:
int numRabbits(vector<int>& answers) {
int res = ;
vector<int> cnt(, );
for (int ans : answers) cnt[ans] = (cnt[ans] + ) % (ans + );
for (int i = ; i < ; ++i) {
if (cnt[i] != ) res += i + - cnt[i];
}
return res + answers.size();
}
};

参考资料:

https://leetcode.com/problems/rabbits-in-forest/solution/

https://leetcode.com/problems/rabbits-in-forest/discuss/123206/Java-4-Liner-No-HashMap

https://leetcode.com/problems/rabbits-in-forest/discuss/114719/My-easy-Java-HashMap-solution

https://leetcode.com/problems/rabbits-in-forest/discuss/114721/Easy-and-Concise-Solution-C++JavaPython

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Rabbits in Forest 森林里的兔子的更多相关文章

  1. LC 781. Rabbits in Forest

    In a forest, each rabbit has some color. Some subset of rabbits (possibly all of them) tell you how ...

  2. LeetCode 781. Rabbits in Forest (森林中的兔子)

    题目标签:HashMap 题目给了我们一组数字,每一个数字代表着这只兔子说 有多少只一样颜色的兔子. 我们把每一个数字和它出现的次数都存入map.然后遍历map,来判断到底有多少个一样颜色的group ...

  3. [Swift]LeetCode781. 森林中的兔子 | Rabbits in Forest

    In a forest, each rabbit has some color. Some subset of rabbits (possibly all of them) tell you how ...

  4. 【LeetCode】781. Rabbits in Forest 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  5. LeetCode解题报告汇总! All in One!

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 把自己刷过的所有题目做一个整理,并且用简洁的语言概括了一下思路,汇总成了一个表格. 题目 ...

  6. Swift LeetCode 目录 | Catalog

    请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift    说明:题目中含有$符号则为付费题目. 如 ...

  7. leetcode 学习心得 (4)

    645. Set Mismatch The set S originally contains numbers from 1 to n. But unfortunately, due to the d ...

  8. 【LeetCode】数学(共106题)

    [2]Add Two Numbers (2018年12月23日,review) 链表的高精度加法. 题解:链表专题:https://www.cnblogs.com/zhangwanying/p/979 ...

  9. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

随机推荐

  1. springMVC中 @RequestParam和@RequestBody的区别

    首先,不可以同时传进@RequestParam和@RequestBody,好像可以传进两个@RequestParam 如果不加@requestparam修饰,相当于 加上@requestparam且各 ...

  2. 使用sessionStorage、localStorage存储数组与对象

    先介绍一下localStorage localStorage对象是HTML5的客户端存储持久化数据的方案.为了能访问到同一个localStorage对象,页面必须来自同一个域名(子域名无效),使用同一 ...

  3. word20161228

    1.principles英[p'rɪnsəplz]美[p'rɪnsəplz]n.原则; 原理; 准则; 道义; 节操; 原则( principle的名词复数 ); 工作原理; [P-] (基督教科学派 ...

  4. java web中使用mysql语句遇到的问题

    1.插入数据时遇到     Parameter index out of range (1 > number of parameters, which is 0).  的问题 有问题的代码: 改 ...

  5. Sql Server 字符串操作总结

    SQL Server 支持两种字符数据类型---常规和Unicode:常规类型包括char 和varchar:unicode包括nchar 和nvarchar.常规的每个字符占用一个字节存储,而uni ...

  6. 【原创】大叔经验分享(7)创建hive表时格式如何选择

    常用格式 textfile 需要定义分隔符,占用空间大,读写效率最低,非常容易发生冲突(分隔符)的一种格式,基本上只有需要导入数据的时候才会使用,比如导入csv文件: ROW FORMAT DELIM ...

  7. vue-cli 3.0

    安装 vue-cli 3.0 时报错 vue-cli3安装遇到的问题,卸载不掉旧版本,导致更新不了 vue-cli 2.9.6 版本卸载不了 作者:Runner_leaf链接:https://www. ...

  8. unity setactive的使用

    1.可以用本身移出布局来实现隐藏 2.RawImage的texture的设置生成的一定要及时消除,避免内存泄漏

  9. 树dp:边覆盖,点覆盖

    #493. 求树的最小支配集 问题描述 对于一棵n个结点的无根树,求它的最小支配集. 最小支配集:指从所有顶点中取尽量少的点组成一个集合,使得剩下的所有点都与取出来的点有边相连.顶点个数最小的支配集被 ...

  10. python下载大文件

    1. wget def download_big_file_with_wget(url, target_file_name): """ 使用wget下载大文件 Note: ...