Maximum subarray sum modulo M
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
The maximum subarray sum modulo M problem asks for the largest value of a contiguous subarray sum after applying modulo M. A brute-force scan checks every subarray and quickly becomes too slow. The efficient solution uses prefix sums modulo M plus a sorted set to find the best wraparound candidate in O(n log n) time.
Start from Prefix Sums Modulo M
Let prefix[i] be the sum of elements up to index i, reduced modulo M. Then the sum of subarray i..j modulo M can be derived from two prefix sums.
If prefix[j] >= prefix[i - 1], the subarray modulo is:
prefix[j] - prefix[i - 1]
If prefix[j] < prefix[i - 1], the modulo wraps and becomes:
prefix[j] - prefix[i - 1] + M
That second case is where the optimal answer often comes from, because values close to M - 1 are best.
Why a Sorted Set Solves It
As you scan from left to right, keep all previous prefix sums in sorted order. For the current prefix p, you want the smallest earlier prefix that is strictly greater than p. If you find such a value q, then:
(p - q + M) % M
is a candidate subarray sum modulo M, and it is often very large because q is only slightly larger than p.
At the same time, the prefix p itself is also a candidate, since the subarray may start at index 0.
Efficient Java Implementation
Java's TreeSet is a natural fit because it supports sorted insertion and the higher() lookup.
This runs in O(n log n) because each step performs a constant number of TreeSet operations.
Why the Naive Approach Is Too Slow
The brute-force approach checks every subarray:
This is O(n^2), or worse if subarray sums are recomputed from scratch. It is fine for tiny arrays and useful for testing, but it does not scale to typical interview or competitive programming input sizes.
The Key Insight
The clever part is realizing that the maximum modulo value does not always come from the numerically largest raw subarray sum. It comes from choosing two prefix sums whose difference, after wraparound, lands as close as possible to M.
That is why the sorted set lookup matters. You are not just comparing current sums. You are searching for the best earlier prefix to subtract.
Common Pitfalls
The biggest mistake is forgetting that prefix values must stay modulo M at every step. Letting them grow without reduction makes the reasoning and the implementation harder than necessary.
Another issue is using the wrong sorted-set lookup. You want the smallest previous prefix strictly greater than the current prefix, not merely the greatest smaller prefix.
People also often overlook negative values. If the array may contain negatives, normalizing the prefix with + mod before the final modulo keeps the result in the expected range.
Finally, beware of integer overflow in languages with narrow numeric types. Use a sufficiently large integer type for prefix calculations before reducing modulo M.
Summary
- Use prefix sums modulo
Mto transform subarray sums into prefix differences. - The best wraparound candidate comes from subtracting the smallest previous prefix greater than the current prefix.
- A sorted structure such as
TreeSetmakes that lookup efficient. - The optimal algorithm runs in
O(n log n), far better than brute force. - The hardest part is the prefix-set insight, not the code itself.

