3212. Count Submatrices With Equal Frequency of X and Y
Problem Description
Given a 2D character matrix grid
, where grid[i][j]
is either 'X'
, 'Y'
, or '.'
, you need to return the number of submatrices that contain:
- The element
grid[0][0]
. - An equal frequency of
'X'
and'Y'
. - At least one
'X'
.
Intuition
To solve this problem, the goal is to find submatrices fulfilling specific conditions efficiently. We employ a 2D prefix sum approach which helps calculate the cumulative frequency of characters 'X'
and 'Y'
up to any given cell (i, j)
.
- Prefix Sum Array: We create a 3D prefix sum array
s
wheres[i][j][0]
tracks the number of'X'
s ands[i][j][1]
tracks the number of'Y'
s from(0, 0)
to(i, j)
. - Calculation: As we iterate through the matrix:
- Update the prefix sum at
(i, j)
using:s[i][j][0] = s[i-1][j][0] + s[i][j-1][0] - s[i-1][j-1][0]
and similarly fors[i][j][1]
.
- Increment
s[i][j][ord(x) & 1]
if the current cell is not'.'
(ord('X') & 1 == 0
,ord('Y') & 1 == 1
).
- Update the prefix sum at
- Checking Condition: For each cell
(i, j)
, check:- If
s[i][j][0]
is greater than zero. - If the number of
'X'
s is equal to'Y'
s. - If both conditions are satisfied, count this submatrix as valid.
- If
This method is efficient because it allows us to check conditions over a grid submatrix using calculated prefix sums, reducing the need for multiple nested loops.
Learn more about Prefix Sum patterns.
Solution Approach
2D Prefix Sum
In this problem, the main challenge is efficiently counting the number of submatrices that meet the criteria. We make use of a 2D prefix sum array to handle this:
-
Initialize Prefix Sum Array: We create a 3D array
s
wheres[i][j][0]
keeps track of the number of'X'
s, ands[i][j][1]
tracks the number of'Y'
s in the submatrix from(0, 0)
to(i, j)
. -
Iterate Over the Grid: As we traverse each cell
(i, j)
in the grid:- Update the prefix sums using:
s[i][j][0] = s[i-1][j][0] + s[i][j-1][0] - s[i-1][j-1][0]
s[i][j][1] = s[i-1][j][1] + s[i][j-1][1] - s[i-1][j-1][1]
- If the current cell
(i, j)
contains either'X'
or'Y'
, increase the appropriate count:s[i][j][ord(grid[i-1][j-1]) & 1] += 1
because the characters are offset by 1.
- Update the prefix sums using:
-
Check Conditions: For each position
(i, j)
, determine if it forms a valid submatrix by checking:s[i][j][0] > 0
, ensuring at least one'X'
is present.s[i][j][0] == s[i][j][1]
, assuring equal counts of'X'
s and'Y'
s.
-
Counting Valid Submatrices: If the conditions hold true, increment the answer by one.
This step-by-step method allows us to efficiently sum up the valid submatrices using prefix sums, reducing computational complexity by avoiding repetitive recalculations.
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 walk through an example to illustrate the solution approach. Consider the following grid:
grid = [ ['X', '.', 'Y'], ['Y', 'X', '.'], ['.', 'Y', 'X'] ]
We aim to find all the submatrices starting from grid[0][0]
, where the frequencies of 'X'
s and 'Y'
s are equal, with at least one 'X'
.
Step 1: Initialize Prefix Sum Array
We start by creating a prefix sum array s
with dimensions [rows+1][cols+1][2]
, initialized to zero. This will store the counts of 'X'
s (index 0) and 'Y'
s (index 1) for each submatrix (0,0)
to (i,j)
.
Step 2: Fill the Prefix Sum Array
Iterate over each cell (i, j)
in grid
, updating the prefix sum:
- For cell
(1, 1)
:- Contains
'X'
:s[1][1][0] = s[0][1][0] + s[1][0][0] - s[0][0][0] + 1
= 1 s[1][1][1] = s[0][1][1] + s[1][0][1] - s[0][0][1]
= 0
- Contains
Continue this process for the entire grid.
Step 3: Check Conditions for Valid Submatrices
For each position (i, j)
, check if the submatrix satisfies the conditions:
(i, j) = (1, 1)
:s[1][1][0] > 0
ensures at least one'X'
.s[1][1][0] == s[1][1][1]
checks equal'X'
and'Y'
.
Proceed with checking submatrices starting from grid[0][0]
by comparing the prefix sums.
Step 4: Count Valid Submatrices
The above conditions help identify valid submatrices. In our example grid, the following submatrices satisfy all conditions:
- Submatrix
[(0,0) to (1,2)]
: Contains 2'X'
s and 2'Y'
s.
Through efficient prefix sum calculations, count these submatrices and return the total number.
This method capitalizes on the prefix sum strategy to minimize redundant calculations, ensuring a more efficient solution.
Solution Implementation
1from typing import List
2
3class Solution:
4 def numberOfSubmatrices(self, grid: List[List[str]]) -> int:
5 # Get the number of rows (m) and columns (n)
6 m, n = len(grid), len(grid[0])
7
8 # Initialize a 3D list to store prefix sum calculations
9 # s[i][j][0] for counting '.' and s[i][j][1] for counting numbers
10 prefix_sum = [[[0] * 2 for _ in range(n + 1)] for _ in range(m + 1)]
11
12 # Initialize the answer variable to count the desired submatrices
13 total_submatrices = 0
14
15 # Iterate over each cell in the grid
16 for i, row in enumerate(grid, 1):
17 for j, value in enumerate(row, 1):
18 # Calculate the prefix sum for '.' (0) and numbers (1)
19 prefix_sum[i][j][0] = (prefix_sum[i - 1][j][0] +
20 prefix_sum[i][j - 1][0] -
21 prefix_sum[i - 1][j - 1][0])
22
23 prefix_sum[i][j][1] = (prefix_sum[i - 1][j][1] +
24 prefix_sum[i][j - 1][1] -
25 prefix_sum[i - 1][j - 1][1])
26
27 # Check if the current value is not a '.'
28 if value != ".":
29 # Increment the appropriate prefix sum based on odd or even character ASCII value
30 prefix_sum[i][j][ord(value) & 1] += 1
31
32 # If submatrix has the same count of '.' and numbers, increment answer
33 if prefix_sum[i][j][0] > 0 and prefix_sum[i][j][0] == prefix_sum[i][j][1]:
34 total_submatrices += 1
35
36 return total_submatrices
37
1class Solution {
2 public int numberOfSubmatrices(char[][] grid) {
3 int rows = grid.length, cols = grid[0].length;
4 int[][][] prefixSums = new int[rows + 1][cols + 1][2];
5 int result = 0;
6
7 // Iterate through each cell in the grid
8 for (int i = 1; i <= rows; ++i) {
9 for (int j = 1; j <= cols; ++j) {
10
11 // Calculate prefix sums for 'X'
12 prefixSums[i][j][0] = prefixSums[i - 1][j][0] + prefixSums[i][j - 1][0]
13 - prefixSums[i - 1][j - 1][0] +
14 (grid[i - 1][j - 1] == 'X' ? 1 : 0);
15
16 // Calculate prefix sums for 'Y'
17 prefixSums[i][j][1] = prefixSums[i - 1][j][1] + prefixSums[i][j - 1][1]
18 - prefixSums[i - 1][j - 1][1] +
19 (grid[i - 1][j - 1] == 'Y' ? 1 : 0);
20
21 // Check if submatrix has the same number of 'X's and 'Y's
22 if (prefixSums[i][j][0] > 0 && prefixSums[i][j][0] == prefixSums[i][j][1]) {
23 ++result;
24 }
25 }
26 }
27
28 return result;
29 }
30}
31
1#include <vector>
2using namespace std;
3
4class Solution {
5public:
6 int numberOfSubmatrices(vector<vector<char>>& grid) {
7 int m = grid.size(), n = grid[0].size();
8
9 // 3D prefix sum array to store counts of 'X' and 'Y'
10 vector<vector<vector<int>>> prefixSum(m + 1, vector<vector<int>>(n + 1, vector<int>(2, 0)));
11 int ans = 0;
12
13 // Calculate prefix sums and check conditions
14 for (int i = 1; i <= m; ++i) {
15 for (int j = 1; j <= n; ++j) {
16 // Calculate prefix sum for 'X'
17 prefixSum[i][j][0] = prefixSum[i - 1][j][0] + prefixSum[i][j - 1][0]
18 - prefixSum[i - 1][j - 1][0] + (grid[i - 1][j - 1] == 'X' ? 1 : 0);
19
20 // Calculate prefix sum for 'Y'
21 prefixSum[i][j][1] = prefixSum[i - 1][j][1] + prefixSum[i][j - 1][1]
22 - prefixSum[i - 1][j - 1][1] + (grid[i - 1][j - 1] == 'Y' ? 1 : 0);
23
24 // If there are equal non-zero numbers of 'X' and 'Y', increment answer
25 if (prefixSum[i][j][0] > 0 && prefixSum[i][j][0] == prefixSum[i][j][1]) {
26 ++ans;
27 }
28 }
29 }
30
31 return ans;
32 }
33};
34
1/**
2 * Computes the number of submatrices within a grid that contain
3 * an equal number of 'X' and 'Y'.
4 * @param grid - A 2D array representing the grid.
5 * @returns The number of submatrices with equal 'X' and 'Y'.
6 */
7function numberOfSubmatrices(grid: string[][]): number {
8 // Dimensions of the grid
9 const [m, n] = [grid.length, grid[0].length];
10
11 // Prefix sum array to count 'X' and 'Y'
12 const prefixSum = Array.from({ length: m + 1 }, () => Array.from({ length: n + 1 }, () => [0, 0]));
13 let answer = 0;
14
15 // Iterate over the grid to populate the prefix sum array
16 for (let i = 1; i <= m; ++i) {
17 for (let j = 1; j <= n; ++j) {
18 // Update the count of 'X'
19 prefixSum[i][j][0] = prefixSum[i - 1][j][0]
20 + prefixSum[i][j - 1][0]
21 - prefixSum[i - 1][j - 1][0]
22 + (grid[i - 1][j - 1] === 'X' ? 1 : 0);
23
24 // Update the count of 'Y'
25 prefixSum[i][j][1] = prefixSum[i - 1][j][1]
26 + prefixSum[i][j - 1][1]
27 - prefixSum[i - 1][j - 1][1]
28 + (grid[i - 1][j - 1] === 'Y' ? 1 : 0);
29
30 // Increase answer if the number of 'X' and 'Y' are equal
31 if (prefixSum[i][j][0] > 0 && prefixSum[i][j][0] === prefixSum[i][j][1]) {
32 ++answer;
33 }
34 }
35 }
36
37 return answer;
38}
39
Time and Space Complexity
The time complexity of the code is O(m \times n)
because it involves iterating over each element of the m x n
grid to compute prefix sums and check conditions, where m
is the number of rows and n
is the number of columns.
The space complexity of the code is O(m \times n)
due to the usage of the 3D list s
, which stores additional data for every element of the m x n
grid.
Learn more about how to find time and space complexity quickly.
Which of the tree traversal order can be used to obtain elements in a binary search tree in sorted order?
Recommended Readings
Prefix Sum The prefix sum is an incredibly powerful and straightforward technique Its primary goal is to allow for constant time range sum queries on an array What is Prefix Sum The prefix sum of an array at index i is the sum of all numbers from index 0 to i By
Coding Interview 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
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!