算法初探LeetCode-森林中的兔子

67 阅读1分钟

LeetCode781. 森林中的兔子

森林中有未知数量的兔子。提问其中若干只兔子 "还有多少只兔子与你(指被提问的兔子)颜色相同?"  ,将答案收集到一个整数数组 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

思路分析

1.数字相同的兔子可能是一种颜色,也可能不是 2.数字不同的兔子一定不是一种颜色 3.颜色相同的兔子,数字一定相同

我们可以按数字种类给兔子分组 例如[2,2,2,3]可分为2组,分别为[2,2,2]和[3] 根据结论3,每一组的兔子和其他任意一组颜色一定不同,也就是说,要使得每类兔子的数字符合要求,首先看本类里面的兔子是否符合要求,例如[2,2,2]就符合要求。如果能凑出,那么这一类就是这么多兔子。如果不能凑出,需要从题目给定的兔子以外去凑,而不能从其他类找,因为颜色一定不同 可以看出每一类是独立的,可以分类统计数量

那怎么判断是否能在本类凑出兔子呢?以官方题解中 13 只兔子回答 5 的例子来说,这13只至少要划为3组不同的颜色,假设前6只为蓝色,中间6只为绿色,最后一只一定是第三种颜色 有没有可能比3更小呢?假设最后一只是蓝色或绿色,那么前面6只或中间6只的数字就不是5,和假设矛盾 因此最少为3组,而最后一只因为也是5,要使得最后一只也满足数字要求,不可能从其他类来凑,因此需要从题目外找5只,也就是18只 也可以是4组,5组,但题目要求数量最少,也就是组数最低,因此这里选3组

算法代码

public int numRabbits(int[] answers) {
    Map < Integer, Integer > map = new HashMap < > ();
    for (int i: answers) {
        map.put(i, map.getOrDefault(i, 0) + 1);
    }

    int res = 0;
    for (int k: map.keySet()) {
        // 在每一类里计算至少需要多少只兔子
        int v = map.get(k);
        int g = v / (k + 1);
        if (v % (k + 1) != 0) {
            g++;
        }
        res += g * (k + 1);
    }
    return res;
}

结果详情

Snipaste_2023-06-01_23-09-46.png

算法复杂度

  • 空间复杂度:O(1)O(1)
  • 时间复杂度:O(n)O(n)

掘金(JUEJIN)一起进步,一起成长!