Day10【LeetCode每日一题】781. 森林中的兔子
题目:
森林中,每个兔子都有颜色。其中一些兔子(可能是全部)告诉你还有多少其他的兔子和自己有相同的颜色。我们将这些回答放在 answers 数组里。
返回森林中兔子的最少数量。
示例:
输入: answers = [1, 1, 2]
输出: 5
解释:
两只回答了 "1" 的兔子可能有相同的颜色,设为红色。
之后回答了 "2" 的兔子不会是红色,否则他们的回答会相互矛盾。
设回答了 "2" 的兔子为蓝色。
此外,森林中还应有另外 2 只蓝色兔子的回答没有包含在数组中。
因此森林中兔子的最少数量是 5: 3 只回答的和 2 只没有回答的。
输入: answers = [10, 10, 10]
输出: 11
输入: answers = []
输出: 0
题解:
本题要求至少需要多少只兔子,那换个题目问你至少需要多少种颜色呢?不妨试试~ 当然在后面代码中,已经实现了这两个功能,可以自己理解一下。
本题题解有两种方法,第一种是直接模拟,第二种是采用哈希表存储数据后,进行计算。
两者方法都是建立在以下基础上的:
假设:answers = [0,0,0,1,1,1]
那么我们可以计算出至少需要5种颜色,7个兔子。前三个兔子回答的都是0,也就是没有其他兔子跟自己颜色相同,那么兔子有1+1+1=3只。当某个兔子回答了x时,数组中至多有x+1个同种颜色的兔子回答x。
例如:[1,1] 至少需要1只兔子,1种颜色即可保证,而[1,1,1]则需要4只兔子,2种颜色保证。同理,到上述answers,前面3只在加上后面4只就是7只,颜色便是3+2=5种。
题解1: 直接模拟
对数组进行排序使得能够方便的跳到下一个颜色兔子。
class Solution {
public:
int numRabbits(vector<int>& answers) {
sort(answers.begin(), answers.end());
int n = answers.size(), ans = 0;
int color = 0;
for (int i = 0; i < n; i++) {
ans += answers[i] + 1;
int k = answers[i];
// 0 0 0 1 1 1 -> 5、7
while (k-- && i + 1 < n && answers[i] == answers[i + 1]) {
i++;
}
color++;
}
cout << color << endl;
return ans;
}
};
时间复杂度:O(nlogn),空间复杂度O(1)
题解2: 使用哈希表
[1,1] 需要1种颜色,2个兔子。[1,1,1] 需要2种颜色,4个兔子。
我们在统计所有回答x的兔子的数量为n,保存到哈希表中。
如果
n % (x+1)==0
,说明只需要n/(x+1)
种不同颜色的兔子,每种颜色兔子的个数为x+1
。如果
n % (x+1) != 0
,说明只需要n/(x+1) + 1
种不同颜色的兔子,每种颜色兔子的个数为x+1
。
class Solution {
public:
int numRabbits(vector<int>& answers) {
unordered_map<int, int> um;
for (auto& x : answers) {
um[x]++;
}
int ans = 0;
int color = 0;
for (auto& [x,n] : um) { // x: n 回答x的兔子有n个
int tmp = ceil((n*1.0/(x+1)));
// n%(x+1)!=0 此时需要n/(x+1) + 1种颜色 每种颜色兔子个数为x+1
color += tmp;
ans += tmp*(x+1);
}
return ans;
}
};
本节完~