Range Addition II: Finding the Overlap of All Operations
You are given an m x n matrix initialized to all zeros and a list of operations ops. Each operation [ai, bi] increments every cell in the sub-rectangle from (0, 0) to (ai - 1, bi - 1) by 1. After applying all operations, you need to count how many cells contain the maximum value. This is LeetCode 598: Range Addition II, and the trick is that you never need to build the matrix at all.
Why this problem matters
At first glance, you might think you need to simulate the operations: allocate the matrix, loop through each operation, increment all the affected cells, then scan for the maximum. That brute-force approach works for small inputs but falls apart when m, n, and the number of operations grow large. The matrix alone could have millions of cells, and you would be iterating over huge sub-rectangles for every operation.
The real lesson here is about recognizing structure. Every operation starts at the top-left corner (0, 0). That means all the affected rectangles are anchored at the same point. The cells that get incremented by every single operation are exactly the cells in the intersection of all those rectangles. And since every rectangle starts at (0, 0), the intersection is also a rectangle starting at (0, 0), extending to the minimum row bound and minimum column bound across all operations.
Once you see that, the entire problem collapses to a single pass through the operations list. No matrix, no nested loops, no simulation. Just find two minimums and multiply them.
The approach
Since every operation [ai, bi] increments the rectangle from (0, 0) to (ai - 1, bi - 1), cell (r, c) is incremented by an operation only if r < ai and c < bi. A cell is incremented by all operations only if r < ai and c < bi for every operation. That means r must be less than the smallest ai, and c must be less than the smallest bi. The count of such cells is min(ai) * min(bi).
def maxCount(m, n, ops):
if not ops:
return m * n
min_row = min(op[0] for op in ops)
min_col = min(op[1] for op in ops)
return min_row * min_col
- If
opsis empty, no increments happen. Every cell stays at 0, so the maximum value is 0 and allm * ncells share it. - Otherwise, find the minimum
aiacross all operations (the tightest row bound) and the minimumbi(the tightest column bound). - The answer is their product:
min_row * min_col.
The intersection is always anchored at the top-left corner because every operation starts at (0, 0). If operations could start at arbitrary positions, you would need a different strategy. But since they all share the same origin, the overlap is simply the smallest rectangle among them.
Step-by-step walkthrough
Let's trace through m = 3, n = 3, ops = [[2, 2], [3, 3]] to see how the overlap shrinks with each operation.
Step 1: Start with a 3x3 zero matrix
All cells begin at 0. We will apply two operations.
Step 2: Apply op [2, 2]
Increment every cell in rows 0..1 and columns 0..1. That is the top-left 2x2 block.
The 2x2 region (highlighted) now has value 1.
Step 3: Apply op [3, 3]
Increment every cell in rows 0..2 and columns 0..2. That covers the entire 3x3 matrix.
The overlap (top-left 2x2) now holds the maximum value of 2.
Step 4: Compute the answer without a matrix
You do not need to build the matrix at all. The overlap region is always anchored at (0, 0) and extends to (min of all ai, min of all bi). Here that is min(2, 3) = 2 rows and min(2, 3) = 2 columns.
Answer = 2 * 2 = 4 cells with the maximum value.
You can see that the answer depends only on the tightest bounds. The second operation covers the whole matrix, but it does not matter because the first operation restricts the overlap to a 2x2 block. Only those 4 cells receive both increments.
Complexity analysis
| Metric | Value | Why |
|---|---|---|
| Time | O(k) | One pass through the k operations to find the two minimums |
| Space | O(1) | Only two variables (min_row and min_col) regardless of input size |
This is as efficient as it gets. You cannot do better than O(k) because you must inspect every operation at least once.
Edge cases to watch for
- Empty ops list: no operations means every cell is 0. The maximum value is 0, and all
m * ncells have it. Returnm * n. - Single operation: the overlap is just that one rectangle. Return
ops[0][0] * ops[0][1]. - An operation equal to
[m, n]: this covers the entire matrix. It does not shrink the overlap at all, it just adds 1 to every cell. - An operation
[1, 1]: only cell(0, 0)is in the rectangle. This forces the overlap down to a single cell. Return 1. - All operations identical: the overlap is the same rectangle repeated. The answer is
ops[0][0] * ops[0][1], and the maximum value equals the number of operations.
The building blocks
The core pattern here is rectangle intersection. When multiple axis-aligned rectangles share a common anchor point, their intersection is determined by the tightest bound along each axis. You take the minimum extent in each dimension and multiply. This same geometric reasoning shows up in problems involving overlapping intervals, bounding boxes, and coordinate compression.
You will also find the "avoid simulation" insight useful in many array and matrix problems. Whenever the problem asks you to apply a series of range updates and then query the result, ask yourself whether you can compute the answer from the operation boundaries alone, without actually performing the updates. That mental shortcut saves you from O(m * n * k) brute force and leads to elegant O(k) solutions.
- Minimum Moves to Equal Array Elements uses a similar reframing trick: instead of simulating increments, you realize the answer depends on a single aggregate value (the minimum element).
- Reshape the Matrix is another matrix problem where index reasoning replaces brute-force simulation.
From understanding to recall
This problem is easy to understand once someone explains it. The intersection-of-rectangles insight clicks immediately. But in an interview, will you remember it? Or will you start writing a nested loop to simulate increments, realize it is too slow, and then scramble to find the pattern under time pressure?
Spaced repetition solves that. You code this solution from scratch today, again in two days, again in five. Each repetition reinforces the connection between "all rectangles anchored at the origin" and "take the min along each axis." After a few reps, you see any range-update problem and automatically ask: can I skip the simulation and work with boundaries instead?
Related posts
- Minimum Moves to Equal Array Elements - Another problem where a clever reframing avoids brute-force simulation
- Reshape the Matrix - Index-based reasoning on a matrix without needing extra data structures
- Set Matrix Zeroes - In-place matrix manipulation using row and column markers