LeetCode 2482 - Difference Between Ones and Zeros in Row and Column
The problem gives us a binary matrix grid with m rows and n columns. Every cell contains either 0 or 1. We must construct another matrix called diff, where each position diff[i][j] depends on how many ones and zeros appear in row i and column j.
Difficulty: 🟡 Medium
Topics: Array, Matrix, Simulation
Solution
LeetCode 2482 - Difference Between Ones and Zeros in Row and Column
Problem Understanding
The problem gives us a binary matrix grid with m rows and n columns. Every cell contains either 0 or 1. We must construct another matrix called diff, where each position diff[i][j] depends on how many ones and zeros appear in row i and column j.
For every cell (i, j), we compute:
$$\text{diff}[i][j] = \text{onesRow}_i + \text{onesCol}_j - \text{zerosRow}_i - \text{zerosCol}_j$$
This means each cell is determined entirely by four counts:
- Number of ones in its row
- Number of ones in its column
- Number of zeros in its row
- Number of zeros in its column
The input matrix itself never changes. We only use it to gather statistics about rows and columns.
The constraints are important:
1 <= m, n <= 10^51 <= m * n <= 10^5
The product m * n is at most 100000, which means the total number of cells is manageable. However, repeatedly scanning rows and columns for every cell would still be inefficient.
A naive implementation could easily become too slow if it recomputes row and column counts for every matrix position separately.
There are several important edge cases:
- A matrix with all ones
- A matrix with all zeros
- A single row matrix
- A single column matrix
- Very rectangular matrices such as
1 x 100000or100000 x 1
The problem guarantees that every value is either 0 or 1, so we never need to handle invalid data.
Approaches
Brute Force Approach
The most direct solution is to compute each diff[i][j] independently.
For every cell (i, j):
- Scan row
iand count ones and zeros. - Scan column
jand count ones and zeros. - Apply the formula.
This approach is correct because every cell receives exactly the values required by the definition.
However, this is inefficient. For every cell, we scan an entire row and an entire column.
If there are m * n cells, and each calculation takes O(m + n), the total complexity becomes:
$$O(m \cdot n \cdot (m + n))$$
This is too slow for the maximum constraints.
Optimal Approach
The key observation is that row and column counts are reused repeatedly.
For example:
- Every cell in the same row shares the same
onesRowandzerosRow. - Every cell in the same column shares the same
onesColandzerosCol.
Instead of recomputing these counts many times, we can precompute them once.
We create:
rowOnes[i]= number of ones in rowicolOnes[j]= number of ones in columnj
Then:
$$\text{zerosRow}_i = n - \text{rowOnes}_i$$
$$\text{zerosCol}_j = m - \text{colOnes}_j$$
Substituting into the formula:
$$\text{diff}[i][j] = \text{rowOnes}[i] + \text{colOnes}[j] - (n - \text{rowOnes}[i]) - (m - \text{colOnes}[j])$$
Simplifying:
$$\text{diff}[i][j] = 2 \cdot \text{rowOnes}[i] + 2 \cdot \text{colOnes}[j] - n - m$$
Now every cell can be computed in constant time after preprocessing.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(m * n * (m + n)) | O(1) | Recomputes row and column counts repeatedly |
| Optimal | O(m * n) | O(m + n) | Precomputes row and column statistics once |
Algorithm Walkthrough
- Determine the matrix dimensions
mandn. - Create two arrays:
rowOnesof sizemcolOnesof sizen
These arrays store how many ones appear in each row and column. 3. Traverse the matrix once.
For every cell (i, j):
-
If
grid[i][j] == 1 -
Increment
rowOnes[i] -
Increment
colOnes[j]
After this pass, we know the number of ones in every row and column.
4. Create the result matrix diff.
5. Traverse the matrix again.
For each cell (i, j):
- Compute zeros in the row:
$$zerosRow = n - rowOnes[i]$$
- Compute zeros in the column:
$$zerosCol = m - colOnes[j]$$
- Apply the formula:
$$diff[i][j] = rowOnes[i] + colOnes[j] - zerosRow - zerosCol$$
6. Return the completed diff matrix.
Why it works
The algorithm works because every diff[i][j] depends only on aggregate information about row i and column j. By preprocessing these aggregates once, we avoid redundant computation.
The counts stored in rowOnes and colOnes are exact, and zeros are derived directly from matrix dimensions. Therefore every computed cell matches the definition from the problem statement.
Python Solution
from typing import List
class Solution:
def onesMinusZeros(self, grid: List[List[int]]) -> List[List[int]]:
m = len(grid)
n = len(grid[0])
row_ones = [0] * m
col_ones = [0] * n
# Count ones in rows and columns
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
row_ones[i] += 1
col_ones[j] += 1
# Build result matrix
diff = [[0] * n for _ in range(m)]
for i in range(m):
for j in range(n):
zeros_row = n - row_ones[i]
zeros_col = m - col_ones[j]
diff[i][j] = (
row_ones[i]
+ col_ones[j]
- zeros_row
- zeros_col
)
return diff
The implementation begins by determining the matrix dimensions. This is necessary because row and column sizes are used repeatedly when calculating zero counts.
The arrays row_ones and col_ones store the number of ones in every row and column. The first nested loop fills these arrays in a single traversal of the matrix.
The second nested loop constructs the final answer matrix. For every cell, the number of zeros is derived mathematically instead of counted explicitly. This avoids unnecessary work and keeps the solution linear in the number of cells.
The algorithm never modifies the input matrix, and every value is computed independently using the preprocessed statistics.
Go Solution
func onesMinusZeros(grid [][]int) [][]int {
m := len(grid)
n := len(grid[0])
rowOnes := make([]int, m)
colOnes := make([]int, n)
// Count ones in rows and columns
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if grid[i][j] == 1 {
rowOnes[i]++
colOnes[j]++
}
}
}
// Build result matrix
diff := make([][]int, m)
for i := 0; i < m; i++ {
diff[i] = make([]int, n)
for j := 0; j < n; j++ {
zerosRow := n - rowOnes[i]
zerosCol := m - colOnes[j]
diff[i][j] = rowOnes[i] +
colOnes[j] -
zerosRow -
zerosCol
}
}
return diff
}
The Go implementation follows exactly the same logic as the Python version. Slices are used for dynamic arrays, and the result matrix is allocated row by row.
Integer overflow is not a concern because the maximum possible value is bounded by m + n, which is at most 200000.
Go requires explicit matrix allocation, so each row of diff is initialized individually.
Worked Examples
Example 1
grid =
[
[0,1,1],
[1,0,1],
[0,0,1]
]
Step 1: Count Ones
| Row | Ones Count |
|---|---|
| 0 | 2 |
| 1 | 2 |
| 2 | 1 |
So:
rowOnes = [2, 2, 1]
Step 2: Count Column Ones
| Column | Ones Count |
|---|---|
| 0 | 1 |
| 1 | 1 |
| 2 | 3 |
So:
colOnes = [1, 1, 3]
Step 3: Compute Each Cell
For (0,0):
onesRow = 2
onesCol = 1
zerosRow = 1
zerosCol = 2
diff[0][0] = 2 + 1 - 1 - 2 = 0
For (0,2):
onesRow = 2
onesCol = 3
zerosRow = 1
zerosCol = 0
diff[0][2] = 2 + 3 - 1 - 0 = 4
Continuing similarly for all cells:
| Cell | Value |
|---|---|
| (0,0) | 0 |
| (0,1) | 0 |
| (0,2) | 4 |
| (1,0) | 0 |
| (1,1) | 0 |
| (1,2) | 4 |
| (2,0) | -2 |
| (2,1) | -2 |
| (2,2) | 2 |
Final result:
[
[0,0,4],
[0,0,4],
[-2,-2,2]
]
Example 2
grid =
[
[1,1,1],
[1,1,1]
]
Step 1: Row Counts
rowOnes = [3, 3]
Step 2: Column Counts
colOnes = [2, 2, 2]
Step 3: Compute Values
For every cell:
onesRow = 3
onesCol = 2
zerosRow = 0
zerosCol = 0
diff = 3 + 2 - 0 - 0 = 5
Final matrix:
[
[5,5,5],
[5,5,5]
]
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(m * n) | Every cell is visited a constant number of times |
| Space | O(m + n) | Stores row and column counts |
The algorithm performs two complete traversals of the matrix. Since the matrix contains m * n cells, the total runtime is linear in the input size.
The extra memory comes from storing row counts and column counts. The output matrix itself is not counted as auxiliary space because it is required by the problem.
Test Cases
from typing import List
class Solution:
def onesMinusZeros(self, grid: List[List[int]]) -> List[List[int]]:
m = len(grid)
n = len(grid[0])
row_ones = [0] * m
col_ones = [0] * n
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
row_ones[i] += 1
col_ones[j] += 1
diff = [[0] * n for _ in range(m)]
for i in range(m):
for j in range(n):
zeros_row = n - row_ones[i]
zeros_col = m - col_ones[j]
diff[i][j] = (
row_ones[i]
+ col_ones[j]
- zeros_row
- zeros_col
)
return diff
sol = Solution()
# Example 1
assert sol.onesMinusZeros([
[0,1,1],
[1,0,1],
[0,0,1]
]) == [
[0,0,4],
[0,0,4],
[-2,-2,2]
]
# Example 2, all ones
assert sol.onesMinusZeros([
[1,1,1],
[1,1,1]
]) == [
[5,5,5],
[5,5,5]
]
# Single cell with zero
assert sol.onesMinusZeros([
[0]
]) == [[-2]]
# Single cell with one
assert sol.onesMinusZeros([
[1]
]) == [[2]]
# All zeros matrix
assert sol.onesMinusZeros([
[0,0],
[0,0]
]) == [
[-4,-4],
[-4,-4]
]
# Single row
assert sol.onesMinusZeros([
[1,0,1,0]
]) == [
[1,1,1,1]
]
# Single column
assert sol.onesMinusZeros([
[1],
[0],
[1]
]) == [
[2],
[0],
[2]
]
# Rectangular matrix
assert sol.onesMinusZeros([
[1,0,0],
[0,1,1]
]) == [
[-1,1,1],
[1,3,3]
]
| Test | Why |
|---|---|
| Example 1 | Validates standard mixed matrix behavior |
| Example 2 | Validates all ones scenario |
| Single cell zero | Smallest possible input with minimum counts |
| Single cell one | Smallest possible input with maximum counts |
| All zeros matrix | Ensures negative values are handled correctly |
| Single row | Tests row-heavy structure |
| Single column | Tests column-heavy structure |
| Rectangular matrix | Validates non-square matrices |
Edge Cases
Single Cell Matrix
A 1 x 1 matrix is the smallest possible input. This case can expose mistakes involving dimensions or index handling. For example, a solution that assumes multiple rows or columns may fail.
The implementation handles this naturally because row and column counts are still computed correctly, even when both dimensions equal one.
All Zeros Matrix
When every cell is zero, all one counts become zero and all zero counts become maximal. This produces negative values throughout the result matrix.
Some incorrect implementations accidentally assume results are always non-negative. The provided solution follows the exact formula and correctly handles negative outputs.
Highly Rectangular Matrices
The constraints allow matrices like 1 x 100000 or 100000 x 1. These shapes can expose inefficiencies in algorithms that repeatedly scan rows or columns.
The optimized solution remains efficient because each cell is processed only a constant number of times. The runtime stays linear in the total number of cells.
All Ones Matrix
If every value is one, then zero counts become zero everywhere. This tests whether the implementation correctly derives zeros using dimensions rather than explicitly counting them.
The algorithm computes:
$$zerosRow = n - rowOnes[i]$$
and
$$zerosCol = m - colOnes[j]$$
which correctly becomes zero in this scenario.