[LeetCode] Rabbits in Forest 森林里的兔子


 

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 = 0;
        unordered_map<int, int> m;      
        for (int ans : answers) {
            if (!m.count(ans + 1) || m[ans + 1] == 0) {
                res += ans + 1;
                m[ans + 1] = ans;
            } else {
                --m[ans + 1];
            }
        }
        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 = 0;
        unordered_map<int, int> m;  
        for (int ans : answers) ++m[ans];
        for (auto a : m) {
            res += (a.second + a.first) / (a.first + 1) * (a.first + 1);
        }
        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 = 0;
        vector<int> cnt(1000, 0); 
        for (int ans : answers) cnt[ans] = (cnt[ans] + 1) % (ans + 1);
        for (int i = 0; i < 1000; ++i) {
            if (cnt[i] != 0) res += i + 1 - 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 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM