1252. Cells with Odd Values in a Matrix
Problem Description
This LeetCode problem presents an m x n
matrix initially filled with all zeroes. We're given a list of indices where each element is a pair [r_i, c_i], indicating a specific row r_i
and column c_i
in the matrix. For each pair of indices, we need to perform two operations:
- Increment all the cells in the specified row
r_i
. - Increment all the cells in the specified column
c_i
.
Our goal is to figure out how many cells in the matrix will have odd values after performing all the specified row and column increments.
Intuition
The intuition behind the solution lies in recognizing that we don't actually need to perform all the increments on the entire matrix to find out how many cells will be odd. Instead, we can track the increment counts separately for rows and columns.
We create two lists, row
of size m
and col
of size n
, to count how many times each row and each column is incremented. When we process the indices, we increment the corresponding count in row
and col
arrays for each given pair [r_i, c_i].
After all increments have been tallied, the value of a cell (i, j) in the matrix will be the sum of increments for its row (i.e., row[i]
) and its column (i.e., col[j]
). If the sum of increments for a cell is odd, then the cell value will be odd. Therefore, the cell will contribute to our final count of odd-valued cells in the matrix.
The code then calculates the total number of odd-valued cells using a simple list comprehension, adding up each possible combination of row[i]
and col[j]
increments and checking if the result is odd ((i + j) % 2
being 1).
This approach avoids the need for a potentially expensive operation of incrementing every cell in the matrix and instead simplifies the problem to a matter of counting increments per row and column.
Learn more about Math patterns.
Solution Approach
The solution uses a straightforward and efficient approach by utilizing additional data structures to keep track of the number of times each row and column is incremented rather than updating the whole matrix directly. Here's a walkthrough of the implementation steps:
-
Initialize two arrays
row
andcol
with sizes corresponding to the number of rowsm
and the number of columnsn
in the matrix, respectively. These will hold the number of times each row and column needs to be incremented.row = [0] * m col = [0] * n
-
Iterate through each given index in the
indices
array. For each pair [r_i, c_i], increment the value at positionr_i
in therow
array and the value at positionc_i
in thecol
array by 1. This step effectively counts the number of times each row and column should be incremented without actually altering the matrix.for r, c in indices: row[r] += 1 col[c] += 1
-
Calculate the number of odd-valued cells. A cell at position (i, j) will have an odd value if the sum of increments from its row and column is odd. To find this, we use a list comprehension that iterates over every possible combination of row and column increments (
row[i]
+col[j]
), and if the sum is odd ((i + j) % 2 == 1
), it contributes to the count.return sum((i + j) % 2 for i in row for j in col)
By running through all combinations of row and column increments, the algorithm efficiently calculates the final count of odd-valued cells after performing all specified operations. This solution avoids the time and space complexity issues that would arise from updating the entire matrix after each increment, thereby offering an optimized way to solve the problem.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's consider a small example with a 3x4
matrix (m=3
, n=4
) and given indices [[0, 1], [1, 1], [2, 2]]
. Here's how the solution approach would work with these inputs:
-
Initialize two arrays
row
andcol
to keep track of the increments:row = [0, 0, 0] # For 3 rows col = [0, 0, 0, 0] # For 4 columns
-
Process the given list of indices:
indices = [[0, 1], [1, 1], [2, 2]] for r, c in indices: row[r] += 1 col[c] += 1 # After processing the indices, we have: row = [1, 1, 1] # Row 0, Row 1, and Row 2 are each incremented once col = [0, 2, 1, 0] # Column 1 is incremented twice and Column 2 once
Our row and col arrays now represent the total number of times each row and column has been incremented.
-
Determine the odd-valued cells in the matrix:
# A cell (i, j) will be odd if (row[i] + col[j]) is odd. odd_count = sum((row[i] + col[j]) % 2 == 1 for i in range(3) for j in range(4)) # Calculate the count: # For i=0 (Row 0): (1+0) % 2, (1+2) % 2, (1+1) % 2, (1+0) % 2 => 1 odd value (at column 1) # For i=1 (Row 1): (1+0) % 2, (1+2) % 2, (1+1) % 2, (1+0) % 2 => 1 odd value (at column 1) # For i=2 (Row 2): (1+0) % 2, (1+2) % 2, (1+1) % 2, (1+0) % 2 => 2 odd values (at columns 1 and 2) # Total odd value count is 4. return odd_count
So, the final count of cells with odd values is 4
for the given example. This method efficiently calculates the odd cell count without modifying the entire matrix, but simply by tracking the number of increments in each row and column.
Solution Implementation
1class Solution:
2 def oddCells(self, rows: int, cols: int, indices: List[List[int]]) -> int:
3 # Initialize two arrays to track the counts of increments in each row and column,
4 # respectively. Initially, all cells have even counts (0).
5 row_counts = [0] * rows
6 col_counts = [0] * cols
7
8 # Loop through each pair of indices representing [row, column].
9 # Increment the corresponding row and column count.
10 for r, c in indices:
11 row_counts[r] += 1
12 col_counts[c] += 1
13
14 # Compute the number of cells with odd values.
15 # For each cell, the value is the sum of the row count and column count.
16 # A cell has an odd value if the sum is an odd number.
17 odd_values_count = sum(
18 (row_count + col_count) % 2
19 for row_count in row_counts
20 for col_count in col_counts
21 )
22
23 # Return the total count of cells with odd values.
24 return odd_values_count
25
1class Solution {
2 public int oddCells(int m, int n, int[][] indices) {
3 // Create arrays to keep track of the increments for rows and columns
4 int[] rowCount = new int[m];
5 int[] colCount = new int[n];
6
7 // Increment the corresponding row and column counters for each index pair
8 for (int[] indexPair : indices) {
9 int rowIndex = indexPair[0];
10 int colIndex = indexPair[1];
11 rowCount[rowIndex]++;
12 colCount[colIndex]++;
13 }
14
15 // Initialize a counter for the number of cells with odd values
16 int oddValueCount = 0;
17
18 // Iterate over each cell to determine if the sum of increments
19 // for the corresponding row and column is odd
20 for (int i = 0; i < m; i++) {
21 for (int j = 0; j < n; j++) {
22 if ((rowCount[i] + colCount[j]) % 2 != 0) {
23 // Increment the count if the cell value is odd
24 oddValueCount++;
25 }
26 }
27 }
28
29 // Return the total count of cells with odd values
30 return oddValueCount;
31 }
32}
33
1#include <vector>
2using namespace std;
3
4class Solution {
5public:
6 // Function to count how many cells will have odd values after performing the operations indicated in 'indices'
7 int oddCells(int numberOfRows, int numberOfColumns, vector<vector<int>>& indices) {
8 vector<int> rows(numberOfRows, 0); // Create a vector to keep track of increments in each row
9 vector<int> cols(numberOfColumns, 0); // Create a vector to keep track of increments in each column
10
11 // Iterate over each pair of indices and increment the relevant rows and columns
12 for (const vector<int>& indexPair : indices) {
13 int rowIndex = indexPair[0];
14 int colIndex = indexPair[1];
15 rows[rowIndex]++;
16 cols[colIndex]++;
17 }
18
19 int oddCount = 0; // Initialize a counter for cells with odd values
20
21 // Nested loop to count the cells that will have odd values
22 for (int i = 0; i < numberOfRows; ++i) {
23 for (int j = 0; j < numberOfColumns; ++j) {
24 // If the sum of the increments for the current cell's row and column is odd, increment oddCount
25 if ((rows[i] + cols[j]) % 2 != 0) {
26 oddCount++;
27 }
28 }
29 }
30
31 // Return the total count of cells with odd values
32 return oddCount;
33 }
34};
35
1// Importing the 'Array' type from TypeScript for type definitions
2import { Array } from "typescript";
3
4// Function to count how many cells will have odd values after performing the operations indicated in 'indices'
5function oddCells(numberOfRows: number, numberOfColumns: number, indices: Array<Array<number>>): number {
6 // Create an array to keep track of increments in each row
7 let rows: Array<number> = new Array(numberOfRows).fill(0);
8 // Create an array to keep track of increments in each column
9 let cols: Array<number> = new Array(numberOfColumns).fill(0);
10
11 // Iterate over each pair of indices and increment the respective rows and columns
12 indices.forEach(indexPair => {
13 let rowIndex: number = indexPair[0];
14 let colIndex: number = indexPair[1];
15 rows[rowIndex]++;
16 cols[colIndex]++;
17 });
18
19 // Initialize a counter for cells with odd values
20 let oddCount: number = 0;
21
22 // Nested loop to count the cells that will have odd values
23 for (let i = 0; i < numberOfRows; i++) {
24 for (let j = 0; j < numberOfColumns; j++) {
25 // If the sum of the increments for the current cell's row and column is odd, increment oddCount
26 if ((rows[i] + cols[j]) % 2 !== 0) {
27 oddCount++;
28 }
29 }
30 }
31
32 // Return the total count of cells with odd values
33 return oddCount;
34}
35
Time and Space Complexity
The time complexity of the provided code is O(m * n + k)
, where m
is the number of rows, n
is the number of columns, and k
is the length of the indices
list. This is because the code consists of a single loop through the indices
list, which takes O(k)
time, followed by a nested loop that iterates through all possible combinations of rows and columns, taking O(m * n)
time. The addition of these two gives the final time complexity.
The space complexity of the code is O(m + n)
, as it requires additional space to store the row
and col
arrays, whose sizes are proportional to the number of rows m
and columns n
, respectively.
Learn more about how to find time and space complexity quickly using problem constraints.
What is an advantages of top-down dynamic programming vs bottom-up dynamic programming?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Want a Structured Path to Master System Design Too? Don’t Miss This!