Day10【LeetCode每日一题】781. 森林中的兔子

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;
    }
};

本节完~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值