Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# 3212. Count Submatrices With Equal Frequency of X and Y

[LeetCode Link](https://leetcode.com/problems/count-submatrices-with-equal-frequency-of-x-and-y/)

Difficulty: Medium
Topics: Array, Matrix, Prefix Sum
Acceptance Rate: 56.0%

## Hints

### Hint 1

The submatrices must always include `grid[0][0]` as the top-left corner. This means every valid submatrix is defined by choosing a bottom-right corner `(i, j)`. Think about how you can efficiently count the number of `'X'` and `'Y'` characters in each such submatrix.

### Hint 2

Since every submatrix shares the same top-left corner `(0, 0)`, you can use a 2D prefix sum to compute the count of `'X'` and `'Y'` in the rectangle from `(0, 0)` to `(i, j)` in O(1) time after an O(m*n) preprocessing step. You need two separate prefix sum arrays — one for `'X'` and one for `'Y'`.

### Hint 3

Build prefix sum arrays `prefX[i][j]` and `prefY[i][j]` where each stores the count of the respective character in the submatrix from `(0,0)` to `(i-1, j-1)`. For each cell `(i, j)`, check if `prefX[i+1][j+1] == prefY[i+1][j+1]` and `prefX[i+1][j+1] > 0`. If both conditions hold, that bottom-right corner produces a valid submatrix.

## Approach

1. **Build two 2D prefix sum arrays** — one for counting `'X'` and one for counting `'Y'`. Use 1-indexed prefix sums for cleaner boundary handling. The recurrence is:

```
prefX[i][j] = prefX[i-1][j] + prefX[i][j-1] - prefX[i-1][j-1] + (grid[i-1][j-1] == 'X' ? 1 : 0)
```

Same formula applies for `prefY` with `'Y'`.

2. **Iterate over every cell** `(i, j)` in the grid. For each cell, query the prefix sums to get `countX = prefX[i+1][j+1]` and `countY = prefY[i+1][j+1]`.

3. **Check the two conditions**: `countX == countY` and `countX > 0`. If both hold, increment the answer.

4. Return the total count.

**Example walkthrough** with `grid = [["X","Y","."],["Y",".","."]`]:

- Submatrix ending at (0,1): contains 1 X and 1 Y → valid.
- Submatrix ending at (0,2): contains 1 X and 1 Y → valid.
- Submatrix ending at (1,1): contains 1 X and 2 Y → invalid.
- Submatrix ending at (1,2): contains 1 X and 2 Y → invalid.
- Submatrix ending at (1,0): contains 1 X and 1 Y → valid.

Total = 3.

## Complexity Analysis

Time Complexity: O(m * n) — one pass to build prefix sums, one pass to count valid submatrices.
Space Complexity: O(m * n) — for the two prefix sum arrays.

## Edge Cases

- **Grid with no `'X'` at all**: Every submatrix has `countX == 0`, so the "at least one X" condition is never met. Answer is 0.
- **Grid with no `'Y'`**: `countX > countY` for every non-trivial submatrix containing an `'X'`, so the equal-frequency condition is never met. Answer is 0.
- **Grid entirely of `'.'`**: Same as no `'X'` — answer is 0.
- **1x1 grid with `'X'`**: The only submatrix has 1 X and 0 Y — not equal. Answer is 0.
- **1x1 grid with `'.'`**: No X present. Answer is 0.
- **Large grid (1000x1000)**: The O(m*n) approach handles this efficiently within constraints.
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
number: "3212"
frontend_id: "3212"
title: "Count Submatrices With Equal Frequency of X and Y"
slug: "count-submatrices-with-equal-frequency-of-x-and-y"
difficulty: "Medium"
topics:
- "Array"
- "Matrix"
- "Prefix Sum"
acceptance_rate: 5604.8
is_premium: false
created_at: "2026-03-19T03:25:19.837760+00:00"
fetched_at: "2026-03-19T03:25:19.837760+00:00"
link: "https://leetcode.com/problems/count-submatrices-with-equal-frequency-of-x-and-y/"
date: "2026-03-19"
---

# 3212. Count Submatrices With Equal Frequency of X and Y

Given a 2D character matrix `grid`, where `grid[i][j]` is either `'X'`, `'Y'`, or `'.'`, return the number of submatrices that contain:

* `grid[0][0]`
* an **equal** frequency of `'X'` and `'Y'`.
* **at least** one `'X'`.





**Example 1:**

**Input:** grid = [["X","Y","."],["Y",".","."]]

**Output:** 3

**Explanation:**

**![](https://assets.leetcode.com/uploads/2024/06/07/examplems.png)**

**Example 2:**

**Input:** grid = [["X","X"],["X","Y"]]

**Output:** 0

**Explanation:**

No submatrix has an equal frequency of `'X'` and `'Y'`.

**Example 3:**

**Input:** grid = [[".","."],[".","."]]

**Output:** 0

**Explanation:**

No submatrix has at least one `'X'`.



**Constraints:**

* `1 <= grid.length, grid[i].length <= 1000`
* `grid[i][j]` is either `'X'`, `'Y'`, or `'.'`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

// countSubmatrices counts submatrices anchored at (0,0) with equal frequency
// of 'X' and 'Y' and at least one 'X', using 2D prefix sums.
func countSubmatrices(grid [][]byte) int {
m := len(grid)
if m == 0 {
return 0
}
n := len(grid[0])

// 1-indexed prefix sums for 'X' and 'Y' counts
prefX := make([][]int, m+1)
prefY := make([][]int, m+1)
for i := 0; i <= m; i++ {
prefX[i] = make([]int, n+1)
prefY[i] = make([]int, n+1)
}

for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
x, y := 0, 0
if grid[i-1][j-1] == 'X' {
x = 1
} else if grid[i-1][j-1] == 'Y' {
y = 1
}
prefX[i][j] = prefX[i-1][j] + prefX[i][j-1] - prefX[i-1][j-1] + x
prefY[i][j] = prefY[i-1][j] + prefY[i][j-1] - prefY[i-1][j-1] + y
}
}

count := 0
for i := 1; i <= m; i++ {
for j := 1; j <= n; j++ {
cx := prefX[i][j]
cy := prefY[i][j]
if cx == cy && cx > 0 {
count++
}
}
}
return count
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package main

import "testing"

func TestCountSubmatrices(t *testing.T) {
tests := []struct {
name string
grid [][]byte
expected int
}{
{
name: "example 1: X Y dot grid",
grid: [][]byte{
{'X', 'Y', '.'},
{'Y', '.', '.'},
},
expected: 3,
},
{
name: "example 2: more X than Y",
grid: [][]byte{
{'X', 'X'},
{'X', 'Y'},
},
expected: 0,
},
{
name: "example 3: all dots",
grid: [][]byte{
{'.', '.'},
{'.', '.'},
},
expected: 0,
},
{
name: "edge case: single X",
grid: [][]byte{{'X'}},
expected: 0,
},
{
name: "edge case: single dot",
grid: [][]byte{{'.'}},
expected: 0,
},
{
name: "edge case: 1x2 with X then Y",
grid: [][]byte{
{'X', 'Y'},
},
expected: 1,
},
{
name: "edge case: no X in grid",
grid: [][]byte{
{'Y', '.'},
{'.', 'Y'},
},
expected: 0,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := countSubmatrices(tt.grid)
if result != tt.expected {
t.Errorf("got %d, want %d", result, tt.expected)
}
})
}
}