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. django drf 基础学习3

    一 简述 这里来谈下一些基本原理 二 汇总 1 restful规范 1 根据method不同做不同的操作          request.method='          get(获取) 返回完整 ...

  2. 迅为iTOP-4418/6818开发板-驱动-IO初始化配置介绍和例程

    对于所有的处理器,pad 一般可以分为两大类:IO(输入输出).Power(VDD 和GDD).类似摄像头 IO.以太网 IO.PWM 的 IO 等等,都可以统称为 IO.一个 IO,有可能能够被配置 ...

  3. matplotlib中的plt.ion()和plt.ioff()函数

    转自https://blog.csdn.net/yzy__zju/article/details/85008603 Matplotlib的显示模式默认为阻塞(block)模式,因此若想动态显示图像,则 ...

  4. celery 大量消息的分布式系统 定时任务

    Celery 1.什么是Celery Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统 专注于实时处理的异步任务队列 同时也支持任务调度 Celery架构 https://www.jia ...

  5. P2947 [USACO09MAR]向右看齐Look Up--单调栈

    单调栈真的很好用呢! P2947 [USACO09MAR]向右看齐Look Up 题目描述 Farmer John's N (1 <= N <= 100,000) cows, conven ...

  6. socket.io中 connect与connection的区别

    参考网址:https://blog.csdn.net/sinat_18474835/article/details/80115961

  7. 如何使用 Lucene 做网站高亮搜索功能?

    现在基本上所有网站都支持搜索功能,现在搜索的工具有很多,比如Solr.Elasticsearch,它们都是基于 Lucene 实现的,各有各的使用场景.Lucene 比较灵活,中小型项目中使用的比较多 ...

  8. Android 杂谈---帧动画

    Android中的动画有 帧动画 属性动画 补间动画 大体思路 1.需要定义存放每一帧的xml文件,放在drawable文件夹下 设置图片路径和duration,以及shot属性,false---&g ...

  9. numpy创建array【老鱼学numpy】

    在上一篇文章中,我们已经看到了如何通过numpy创建numpy中的数组,这里再重复一下: import numpy as np # 数组 a = [[1, 2, 3], [4, 5, 6]] prin ...

  10. c++中字符串的反转

    1.对于用char定义的字符串:使用string.h中的strrev函数 #include <iostream> #include <cstring> using namesp ...