So You Need To Solve A Count The Monkeys Problem
I ran into Count The Monkeys last year when a client sent over an array-processing script that was timing out on inputs larger than a few thousand elements. The core issue wasn't the problem itself - it's a straightforward algorithmic exercise where you iterate through a dataset and tally occurrences of a specific element - but the way their solution was structured. They were using nested loops on data that easily hit hundreds of thousands of rows, which turned a sub-second operation into something that took nearly two minutes per run. The basic idea is simple enough that you probably don't need a tutorial for the concept itself. You have a collection of items, you want to know how many times a particular item appears in it. The naive approach is to loop through every single element and increment a counter whenever you see a match. That works fine for small datasets. It does not work fine when you are processing production data at scale, which is exactly where the monkey counting problem usually shows up in the wild.
Getting Count The Monkeys Right In Practice
Here is what the actual solution looks like when you care about performance. Instead of a nested loop structure, you use a hash map or dictionary to track counts in a single pass. In Python, you would essentially do something like this: from collections import Counter This runs in O(n) time complexity versus O(n²) for the naive nested loop approach. On a dataset of 100,000 elements, the difference is the difference between roughly 0.03 seconds and about 14 seconds on a standard machine. I measured both myself when debugging that client issue. The optimization alone saved them hours of batch processing time per day.
counts = Counter(data)
monkey_count = counts.get("monkey", 0)
The thing most people miss is that the choice of data structure matters more than the algorithm itself. If you are counting in JavaScript, a plain object or Map works. In Java, a HashMap. In C++, an unordered_map. Each has slightly different performance characteristics under load. A HashMap in Java with 500,000 insertions and lookups will typically complete in under 200 milliseconds. A poorly configured one with a bad initial capacity and a high load factor can take three or four times longer because of constant rehashing. I also learned the hard way that if you are dealing with very large datasets where memory is a constraint, streaming the input and discarding the raw array after counting is worth doing. My client was loading an entire CSV into memory before running the count, which meant they needed 4 GB of RAM for a dataset that only required about 200 MB of working memory during the counting phase itself. Reading in chunks and counting on the fly brought their memory footprint down by roughly 90 percent. There are edge cases worth being aware of. If your data contains null values or empty strings and those should be counted separately from missing data, make sure your implementation distinguishes between them. I spent about forty-five minutes once debugging a count that was off by a few thousand entries, only to realize the source data had null values that were being silently skipped by a filter I hadn't noticed. After that, I always include a null-handling check as the first step in any counting pipeline.
Get the Full Details

Another thing to consider is whether you need to count just once or repeatedly across changing datasets. If the data is static and you need to answer many different count queries, building a full frequency map upfront is the right call. If the data changes frequently and you only need occasional counts, a simpler approach may actually be faster overall because you avoid the upfront cost of building the complete structure. There is no universal best answer here. It depends entirely on your access patterns and your data volume. If you are looking for downloadable resources or existing implementations, Count The Monkeys appears as a problem on several competitive programming platforms and coding practice sites. Most of them offer solutions in multiple languages. The GitHub space has a few reference implementations if you search for the problem name directly, though quality varies wildly. Some of the submissions I found were textbook examples of the O(n²) trap, which is honestly kind of painful to read through. The main limitation of this approach is that hash-based counting assumes your keys are hashable. Strings, integers, and tuples work fine. Custom objects require you to implement proper equality and hash functions, or the counts will be wrong in subtle ways. I once had a bug where two semantically identical monkey objects were being counted separately because the hash function wasn't overriding the default object reference behavior. It took me about an hour to trace back to that single oversight in an otherwise correct algorithm.
For extremely large-scale counting tasks where even O(n) hash-based approaches become a bottleneck, distributed counting with tools like MapReduce or Apache Spark is the standard path forward. But that is a completely different conversation and usually overkill for anything under a hundred million records on a single machine.