java codility Max-Counters
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
The Codility Max Counters problem looks simple until you try the obvious solution. Incrementing one counter is cheap, but the “set all counters to the current maximum” operation becomes expensive if you eagerly update the whole array every time. The efficient solution uses lazy updates so the whole algorithm stays linear.
The Problem Shape
You have N counters, all starting at 0, and an array of operations A.
Each value in A means one of two things:
- if
1 <= A[K] <= N, increase counterA[K] - 1 - if
A[K] == N + 1, set all counters to the maximum current counter value
The naive solution updates every counter on each max operation, which can degrade to O(N * M).
The Key Optimization: Lazy Max Updates
The trick is to avoid writing the max value into every counter immediately. Instead, keep two extra values:
- '
currentMax: the highest counter value seen so far' - '
baseline: the value all counters should be at least equal to after the latest max operation'
When you later touch an individual counter, first bring it up to baseline if it was left behind.
That turns repeated full-array writes into cheap comparisons.
Java Implementation
Here is the standard linear-time approach.
Output:
Why It Works
Suppose a max operation happens when currentMax is 7. Instead of writing 7 into every slot, the algorithm sets baseline = 7.
Later, when a specific counter is incremented, the code checks whether that counter is still below baseline. If it is, the counter is first synchronized to baseline, then incremented.
At the very end, one final pass updates any untouched counters that still trail the last baseline.
That gives the same final result as the naive approach without paying repeated full-array update costs.
Complexity
The runtime is O(N + M):
- one pass through the operations array
- one final pass through the counters
The space complexity is O(N) for the counters array.
This is exactly the improvement Codility is testing for.
Common Pitfalls
A common mistake is eagerly applying the max operation to every counter. That is correct but too slow for large inputs.
Another mistake is forgetting to synchronize a counter with baseline before incrementing it. If you skip that, counters that missed earlier max operations stay too small.
A third issue is forgetting the final cleanup pass. Some counters may never be touched again after the last max operation, so they still need to be raised to the baseline before returning the answer.
Summary
- The naive algorithm is too slow because max operations can update the full array repeatedly
- The efficient solution uses lazy propagation with
currentMaxandbaseline - Synchronize a counter with
baselineonly when it is touched or during the final pass - The optimized runtime is
O(N + M) - This problem is mainly about recognizing and implementing deferred updates correctly
Related reading
- java codility training Genomic-range-query
- Java, find intersection of two arrays
- Java implementation of Sieve of Eratosthenes that can go past n 232?
- java indexofString str method complexity
- Java concurrency Countdown latch vs Cyclic barrier
- Java ConcurrentHashMap actions atomicity
- Java recursive Fibonacci sequence
- Java Sorting an array based on another array with indexOf method

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.