Facebook Pixel

781. Rabbits in Forest

Problem Description

You have a forest containing an unknown number of rabbits. You approach n rabbits and ask each one: "How many other rabbits have the same color as you?" Each rabbit gives you a number, and these responses are collected in an array called answers, where answers[i] represents the response from the i-th rabbit.

The key insight is that when a rabbit says there are x other rabbits with the same color, it means there are x + 1 total rabbits of that color (including itself).

Your task is to determine the minimum possible number of rabbits that could exist in the forest based on these answers.

For example:

  • If a rabbit answers "1", it means there are 2 rabbits total of its color (itself + 1 other)
  • If two rabbits both answer "1", they could potentially be the same color (meaning just 2 rabbits total), fulfilling both their statements
  • If three rabbits all answer "1", at least two different colors must exist since each color group of size 2 can only contain 2 rabbits, requiring a minimum of 4 rabbits total (2 of one color, 2 of another)

The challenge is to group the rabbits optimally to minimize the total count while ensuring all answers remain valid.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

When a rabbit says there are x other rabbits with the same color, we know that color group must have exactly x + 1 rabbits total. The key insight is that multiple rabbits giving the same answer could potentially belong to the same color group.

Let's think through this step by step. If we have multiple rabbits all saying "2", each is claiming to be part of a group of 3 rabbits. Could they all be the same color? Well, if we have 3 or fewer rabbits saying "2", they could all be the same color (one group of 3). But if we have 4 rabbits saying "2", we'd need at least 2 color groups since one group can only hold 3 rabbits.

This leads us to a greedy approach: for rabbits giving the same answer x, we should pack them into groups of size x + 1 as efficiently as possible. If we have v rabbits giving answer x, and each color group holds x + 1 rabbits, we need ceil(v / (x + 1)) groups.

The ceiling division can be calculated as (v + x) // (x + 1), and since each group contains x + 1 rabbits, the total number of rabbits for this answer is ceil(v / (x + 1)) * (x + 1), which equals ((v + x) // (x + 1)) * (x + 1).

By using a hash map to count occurrences of each answer and applying this formula to each unique answer, we can calculate the minimum total number of rabbits needed to satisfy all the given answers.

Learn more about Greedy and Math patterns.

Solution Approach

The solution uses a greedy approach with a hash map to efficiently calculate the minimum number of rabbits.

Step 1: Count the occurrences of each answer We use Counter(answers) to create a hash map cnt where the key is the answer value x and the value is the number of rabbits v that gave that answer.

Step 2: Process each unique answer For each unique answer x with count v in the hash map:

  • Calculate the group size: group = x + 1 (since a rabbit saying x means there are x + 1 rabbits of that color)
  • Determine the minimum number of groups needed using ceiling division: (v + group - 1) // group
  • Calculate the total rabbits for this answer: ((v + group - 1) // group) * group

Step 3: Sum up all rabbits Add the calculated rabbits from each unique answer to get the final result.

The formula (v + group - 1) // group * group effectively performs:

  • Ceiling division to find the number of complete groups needed
  • Multiplication by group size to get the total rabbits

For example, if 5 rabbits answer "2":

  • Group size = 2 + 1 = 3
  • Number of groups = (5 + 3 - 1) // 3 = 7 // 3 = 2 groups
  • Total rabbits = 2 × 3 = 6 rabbits

This ensures we use the minimum number of color groups while satisfying all the given answers.

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the example answers = [1, 1, 2, 2, 2].

Step 1: Count occurrences Using a hash map to count each answer:

  • Answer "1" appears 2 times
  • Answer "2" appears 3 times

Step 2: Process answer "1" (appears 2 times)

  • A rabbit answering "1" means its color group has 1 + 1 = 2 rabbits total
  • We have 2 rabbits giving this answer
  • Number of groups needed: (2 + 2 - 1) // 2 = 3 // 2 = 1 group
  • Total rabbits for this answer: 1 group × 2 rabbits/group = 2 rabbits
  • These 2 rabbits can both be the same color (e.g., both red)

Step 3: Process answer "2" (appears 3 times)

  • A rabbit answering "2" means its color group has 2 + 1 = 3 rabbits total
  • We have 3 rabbits giving this answer
  • Number of groups needed: (3 + 3 - 1) // 3 = 5 // 3 = 1 group
  • Total rabbits for this answer: 1 group × 3 rabbits/group = 3 rabbits
  • These 3 rabbits can all be the same color (e.g., all blue)

Step 4: Calculate total

  • Rabbits from answer "1": 2
  • Rabbits from answer "2": 3
  • Total minimum rabbits: 2 + 3 = 5

This gives us the minimum configuration: 2 red rabbits (both saying "1") and 3 blue rabbits (all saying "2"), for a total of 5 rabbits in the forest.

Solution Implementation

1from typing import List
2from collections import Counter
3
4class Solution:
5    def numRabbits(self, answers: List[int]) -> int:
6        # Count frequency of each answer
7        # Key: answer value (number of other rabbits with same color)
8        # Value: how many rabbits gave this answer
9        answer_counts = Counter(answers)
10      
11        # Initialize minimum total rabbits
12        total_rabbits = 0
13      
14        # Process each unique answer and its frequency
15        for answer_value, frequency in answer_counts.items():
16            # Calculate group size for this color
17            # If a rabbit says there are 'x' others with same color,
18            # then total rabbits of that color = x + 1 (including itself)
19            group_size = answer_value + 1
20          
21            # Calculate minimum number of groups needed
22            # Using ceiling division: (frequency + group_size - 1) // group_size
23            # This gives us the minimum number of complete groups needed
24            num_groups = (frequency + group_size - 1) // group_size
25          
26            # Add total rabbits from all groups of this color
27            # Each group has 'group_size' rabbits
28            total_rabbits += num_groups * group_size
29      
30        return total_rabbits
31
1class Solution {
2    public int numRabbits(int[] answers) {
3        // Map to store frequency of each answer
4        // Key: number of other rabbits with same color (answer value)
5        // Value: count of rabbits giving this answer
6        Map<Integer, Integer> answerFrequency = new HashMap<>();
7      
8        // Count frequency of each answer
9        for (int answer : answers) {
10            answerFrequency.merge(answer, 1, Integer::sum);
11        }
12      
13        // Calculate minimum number of rabbits
14        int totalRabbits = 0;
15      
16        // Process each unique answer and its frequency
17        for (Map.Entry<Integer, Integer> entry : answerFrequency.entrySet()) {
18            int otherRabbitsWithSameColor = entry.getKey();
19            int rabbitCount = entry.getValue();
20          
21            // Group size = answer + 1 (including the rabbit itself)
22            int groupSize = otherRabbitsWithSameColor + 1;
23          
24            // Calculate minimum number of groups needed
25            // Using ceiling division: (rabbitCount + groupSize - 1) / groupSize
26            // Then multiply by groupSize to get total rabbits
27            int numberOfGroups = (rabbitCount + groupSize - 1) / groupSize;
28            totalRabbits += numberOfGroups * groupSize;
29        }
30      
31        return totalRabbits;
32    }
33}
34
1class Solution {
2public:
3    int numRabbits(vector<int>& answers) {
4        // Map to store frequency of each answer
5        // Key: number of other rabbits with same color (as reported)
6        // Value: count of rabbits reporting this number
7        unordered_map<int, int> frequencyMap;
8      
9        // Count the frequency of each answer
10        for (int answer : answers) {
11            ++frequencyMap[answer];
12        }
13      
14        // Calculate minimum number of rabbits
15        int minRabbits = 0;
16      
17        // Process each unique answer and its frequency
18        for (auto& [otherRabbits, frequency] : frequencyMap) {
19            // If a rabbit says there are 'otherRabbits' other rabbits with same color,
20            // then there are at most (otherRabbits + 1) rabbits in that color group
21            int groupSize = otherRabbits + 1;
22          
23            // Calculate minimum number of groups needed for 'frequency' rabbits
24            // reporting the same answer
25            // Formula: ceiling(frequency / groupSize) * groupSize
26            // which equals (frequency + groupSize - 1) / groupSize * groupSize
27            int numGroups = (frequency + groupSize - 1) / groupSize;
28            minRabbits += numGroups * groupSize;
29        }
30      
31        return minRabbits;
32    }
33};
34
1/**
2 * Calculates the minimum number of rabbits that could be in the forest
3 * based on their color group answers
4 * @param answers - Array where each element represents a rabbit's answer about
5 *                  how many other rabbits have the same color
6 * @returns The minimum possible number of rabbits in the forest
7 */
8function numRabbits(answers: number[]): number {
9    // Map to store frequency of each answer
10    // Key: rabbit's answer, Value: count of rabbits giving this answer
11    const answerFrequency = new Map<number, number>();
12  
13    // Count frequency of each answer
14    for (const answer of answers) {
15        answerFrequency.set(answer, (answerFrequency.get(answer) || 0) + 1);
16    }
17  
18    // Calculate minimum total rabbits
19    let totalRabbits = 0;
20  
21    // Process each unique answer and its frequency
22    for (const [answer, frequency] of answerFrequency.entries()) {
23        // If a rabbit says there are 'answer' other rabbits with same color,
24        // then the group size is answer + 1 (including itself)
25        const groupSize = answer + 1;
26      
27        // Calculate minimum number of complete groups needed
28        // Using ceiling division: Math.floor((frequency + groupSize - 1) / groupSize)
29        // This gives us the number of color groups required
30        const numberOfGroups = Math.floor((frequency + groupSize - 1) / groupSize);
31      
32        // Add total rabbits from all groups of this size
33        totalRabbits += numberOfGroups * groupSize;
34    }
35  
36    return totalRabbits;
37}
38

Time and Space Complexity

The time complexity is O(n), where n is the length of the array answers. This is because:

  • Creating the Counter takes O(n) time as it needs to iterate through all elements in answers
  • Iterating through the Counter items takes O(k) time where k is the number of unique values, and k ≤ n
  • Each operation inside the loop (arithmetic operations) takes O(1) time
  • Overall: O(n) + O(k) × O(1) = O(n)

The space complexity is O(n), where n is the length of the array answers. This is because:

  • The Counter cnt stores at most n key-value pairs (in the worst case where all answers are unique)
  • The variable ans uses O(1) additional space
  • Overall: O(n) + O(1) = O(n)

Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall 1: Incorrectly Assuming All Rabbits with Same Answer Have Same Color

The Mistake: A common misconception is thinking that if multiple rabbits give the same answer, they must all be the same color. For instance, if 5 rabbits all answer "2", one might incorrectly assume they're all the same color, leading to counting only 3 rabbits total.

Why It's Wrong: If a rabbit answers "2", there must be exactly 3 rabbits of its color (itself + 2 others). A group of 3 rabbits cannot accommodate 5 rabbits, so multiple color groups are needed.

Correct Approach:

# Wrong approach - assumes all same answers = same color
def wrong_solution(answers):
    unique_answers = set(answers)
    total = 0
    for answer in unique_answers:
        total += answer + 1  # This ignores frequency!
    return total

# Correct approach - considers frequency
def correct_solution(answers):
    answer_counts = Counter(answers)
    total = 0
    for answer, frequency in answer_counts.items():
        group_size = answer + 1
        num_groups = (frequency + group_size - 1) // group_size
        total += num_groups * group_size
    return total

Pitfall 2: Using Floor Division Instead of Ceiling Division

The Mistake: Using regular floor division (frequency // group_size) instead of ceiling division when calculating the number of groups needed.

Example of the Error: If 5 rabbits answer "2" (group size = 3):

  • Floor division: 5 // 3 = 1 group → 3 rabbits total (incorrect - doesn't account for all 5 rabbits)
  • Ceiling division: (5 + 3 - 1) // 3 = 2 groups → 6 rabbits total (correct)

Solution: Always use the ceiling division formula: (frequency + group_size - 1) // group_size

Alternatively, you can use:

import math
num_groups = math.ceil(frequency / group_size)

Pitfall 3: Forgetting Edge Cases

The Mistake: Not handling special cases properly, particularly when answer = 0.

Why It Matters: When a rabbit answers "0", it means it's the only rabbit of its color. Each rabbit answering "0" must be a different color.

Example:

# Input: [0, 0, 0]
# Wrong thinking: 1 rabbit total
# Correct: 3 rabbits (each answering "0" is alone, so 3 different colors)

# The formula handles this correctly:
# group_size = 0 + 1 = 1
# For 3 rabbits answering "0": (3 + 1 - 1) // 1 * 1 = 3

The ceiling division formula naturally handles this edge case without special treatment.

Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Which of the following is a min heap?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More