2352. Equal Row and Column Pairs
Problem Description
You are given a square matrix grid
of size n x n
containing integers. Your task is to count how many pairs of rows and columns are equal to each other.
A row-column pair (ri, cj)
consists of:
- Row
ri
: the i-th row of the matrix - Column
cj
: the j-th column of the matrix
A row and a column are considered equal if they have the exact same elements in the exact same order. For example, if row 2 is [1, 2, 3]
and column 0 is [1, 2, 3]
, they form an equal pair.
The solution iterates through all possible row-column combinations. For each pair (i, j)
, it checks if row i
matches column j
by comparing element by element. Specifically, it verifies that grid[i][0]
equals grid[0][j]
, grid[i][1]
equals grid[1][j]
, and so on for all n
elements. If all elements match in order, the counter is incremented.
The time complexity is O(n³)
since we check n²
pairs and each comparison takes O(n)
time to verify all elements.
Intuition
The key insight is recognizing that we need to compare sequences of elements. Since we're working with a square matrix, every row has exactly n
elements and every column also has exactly n
elements, making them directly comparable.
To check if a row and column are equal, we need to verify that their elements match position by position. For row i
and column j
to be equal:
- The first element of row
i
(which isgrid[i][0]
) must equal the first element of columnj
(which isgrid[0][j]
) - The second element of row
i
(which isgrid[i][1]
) must equal the second element of columnj
(which isgrid[1][j]
) - And so on for all
n
positions
This pattern reveals that for the k-th position, we're comparing grid[i][k]
with grid[k][j]
. Notice how the row index stays constant at i
while we vary the column index k
, and for the column, the column index stays constant at j
while we vary the row index k
.
The brute force approach naturally emerges: try every possible row-column pair. Since we have n
rows and n
columns, we have n²
total pairs to check. For each pair, we perform an element-by-element comparison. The all()
function elegantly handles this by checking if all elements at corresponding positions are equal, returning True
only when the entire row matches the entire column.
Solution Approach
The solution uses a straightforward simulation approach with nested loops to check all possible row-column pairs.
Implementation Steps:
-
Initialize the counter: Start with
ans = 0
to keep track of equal row-column pairs. -
Iterate through all pairs: Use two nested loops where
i
represents the row index (from 0 to n-1) andj
represents the column index (from 0 to n-1). This generates alln²
possible(ri, cj)
pairs. -
Compare row i with column j: For each pair
(i, j)
, we need to check if rowi
equals columnj
. This is done using:all(grid[i][k] == grid[k][j] for k in range(n))
This generator expression checks each position
k
from 0 to n-1:grid[i][k]
gives us the k-th element of rowi
grid[k][j]
gives us the k-th element of columnj
- The
all()
function returnsTrue
only if every comparison isTrue
-
Count matches: When
all()
returnsTrue
, it means rowi
and columnj
are equal. In Python,True
is treated as 1 andFalse
as 0, so we can directly add the result to our answer:ans += all(grid[i][k] == grid[k][j] for k in range(n))
-
Return the result: After checking all
n²
pairs, return the total count.
The algorithm doesn't require any additional data structures beyond the input matrix. The space complexity is O(1)
(excluding the input), and the time complexity is O(n³)
- we have n²
pairs to check, and each comparison takes O(n)
time.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a small example to illustrate the solution approach.
Consider the following 3×3 matrix:
grid = [[3, 2, 1], [1, 7, 6], [2, 7, 7]]
We need to find all row-column pairs where the row and column have identical elements in the same order.
Step 1: Initialize counter
ans = 0
n = 3
(matrix size)
Step 2: Check all row-column pairs
Let's examine each pair (i, j):
Pair (0, 0): Compare row 0 [3, 2, 1]
with column 0 [3, 1, 2]
- Position 0:
grid[0][0]
= 3 vsgrid[0][0]
= 3 ✓ - Position 1:
grid[0][1]
= 2 vsgrid[1][0]
= 1 ✗ - Not equal, move on
Pair (0, 1): Compare row 0 [3, 2, 1]
with column 1 [2, 7, 7]
- Position 0:
grid[0][0]
= 3 vsgrid[0][1]
= 2 ✗ - Not equal, move on
Pair (0, 2): Compare row 0 [3, 2, 1]
with column 2 [1, 6, 7]
- Position 0:
grid[0][0]
= 3 vsgrid[0][2]
= 1 ✗ - Not equal, move on
Pair (1, 0): Compare row 1 [1, 7, 6]
with column 0 [3, 1, 2]
- Position 0:
grid[1][0]
= 1 vsgrid[0][0]
= 3 ✗ - Not equal, move on
Pair (1, 1): Compare row 1 [1, 7, 6]
with column 1 [2, 7, 7]
- Position 0:
grid[1][0]
= 1 vsgrid[0][1]
= 2 ✗ - Not equal, move on
Pair (1, 2): Compare row 1 [1, 7, 6]
with column 2 [1, 6, 7]
- Position 0:
grid[1][0]
= 1 vsgrid[0][2]
= 1 ✓ - Position 1:
grid[1][1]
= 7 vsgrid[1][2]
= 6 ✗ - Not equal, move on
Pair (2, 0): Compare row 2 [2, 7, 7]
with column 0 [3, 1, 2]
- Position 0:
grid[2][0]
= 2 vsgrid[0][0]
= 3 ✗ - Not equal, move on
Pair (2, 1): Compare row 2 [2, 7, 7]
with column 1 [2, 7, 7]
- Position 0:
grid[2][0]
= 2 vsgrid[0][1]
= 2 ✓ - Position 1:
grid[2][1]
= 7 vsgrid[1][1]
= 7 ✓ - Position 2:
grid[2][2]
= 7 vsgrid[2][1]
= 7 ✓ - Match found!
ans = 1
Pair (2, 2): Compare row 2 [2, 7, 7]
with column 2 [1, 6, 7]
- Position 0:
grid[2][0]
= 2 vsgrid[0][2]
= 1 ✗ - Not equal, move on
Step 3: Return result
- Total equal pairs found:
1
The only equal row-column pair is (row 2, column 1), both containing [2, 7, 7]
.
Solution Implementation
1class Solution:
2 def equalPairs(self, grid: List[List[int]]) -> int:
3 """
4 Count the number of pairs where a row equals a column in the grid.
5
6 Args:
7 grid: A square matrix (n x n) of integers
8
9 Returns:
10 The number of (row, column) pairs where row i equals column j
11 """
12 n = len(grid)
13 pair_count = 0
14
15 # Iterate through all possible row-column pairs
16 for row_index in range(n):
17 for col_index in range(n):
18 # Check if row at row_index equals column at col_index
19 # by comparing each element at position k
20 is_equal = all(grid[row_index][k] == grid[k][col_index] for k in range(n))
21
22 # Increment counter if row equals column
23 if is_equal:
24 pair_count += 1
25
26 return pair_count
27
1class Solution {
2 /**
3 * Counts the number of equal row-column pairs in a square grid.
4 * A row and column pair is considered equal if all corresponding elements are equal.
5 *
6 * @param grid A square 2D integer array
7 * @return The count of equal row-column pairs
8 */
9 public int equalPairs(int[][] grid) {
10 int gridSize = grid.length;
11 int equalPairCount = 0;
12
13 // Iterate through each possible row index
14 for (int rowIndex = 0; rowIndex < gridSize; ++rowIndex) {
15 // Iterate through each possible column index
16 for (int colIndex = 0; colIndex < gridSize; ++colIndex) {
17 boolean isEqual = true;
18
19 // Compare elements of row[rowIndex] with column[colIndex]
20 for (int position = 0; position < gridSize; ++position) {
21 // Check if element at row[rowIndex][position] equals element at column[position][colIndex]
22 if (grid[rowIndex][position] != grid[position][colIndex]) {
23 isEqual = false;
24 break;
25 }
26 }
27
28 // Increment count if the row and column are equal
29 if (isEqual) {
30 equalPairCount++;
31 }
32 }
33 }
34
35 return equalPairCount;
36 }
37}
38
1class Solution {
2public:
3 int equalPairs(vector<vector<int>>& grid) {
4 int n = grid.size();
5 int count = 0; // Total count of equal row-column pairs
6
7 // Iterate through each row index
8 for (int row = 0; row < n; ++row) {
9 // Iterate through each column index
10 for (int col = 0; col < n; ++col) {
11 bool isEqual = true; // Flag to check if row[row] equals column[col]
12
13 // Compare each element of row[row] with corresponding element of column[col]
14 for (int k = 0; k < n; ++k) {
15 // Check if element at position k in row doesn't match element at position k in column
16 if (grid[row][k] != grid[k][col]) {
17 isEqual = false;
18 break; // Early exit if mismatch found
19 }
20 }
21
22 // Increment count if the row and column are equal
23 if (isEqual) {
24 count++;
25 }
26 }
27 }
28
29 return count;
30 }
31};
32
1/**
2 * Counts the number of equal row-column pairs in a square grid.
3 * A row-column pair (i, j) is equal if row i and column j contain
4 * the same elements in the same order.
5 *
6 * @param grid - A square matrix of numbers
7 * @returns The count of equal row-column pairs
8 */
9function equalPairs(grid: number[][]): number {
10 const gridSize: number = grid.length;
11 let pairCount: number = 0;
12
13 // Iterate through each possible row-column pair
14 for (let rowIndex = 0; rowIndex < gridSize; rowIndex++) {
15 for (let colIndex = 0; colIndex < gridSize; colIndex++) {
16 let isEqual: number = 1; // Flag to track if current pair is equal
17
18 // Compare elements of row[rowIndex] with column[colIndex]
19 for (let elementIndex = 0; elementIndex < gridSize; elementIndex++) {
20 // Check if row element differs from corresponding column element
21 if (grid[rowIndex][elementIndex] !== grid[elementIndex][colIndex]) {
22 isEqual = 0; // Mark as not equal
23 break; // No need to check further
24 }
25 }
26
27 // Add to count if the row-column pair is equal
28 pairCount += isEqual;
29 }
30 }
31
32 return pairCount;
33}
34
Time and Space Complexity
The time complexity is O(n^3)
, where n
is the number of rows or columns in the matrix grid
. This is because:
- The outer two loops iterate through all pairs of
(i, j)
positions, contributingO(n^2)
iterations - For each pair, the
all()
function with the generator expression checksn
elements by comparinggrid[i][k]
withgrid[k][j]
for allk
from0
ton-1
, contributingO(n)
operations - Therefore, the total time complexity is
O(n^2) × O(n) = O(n^3)
The space complexity is O(1)
. The algorithm only uses a constant amount of extra space for variables n
, ans
, i
, j
, and the iterator k
in the generator expression. The generator expression itself doesn't create any additional data structures and evaluates lazily, using constant space.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Confusing Row-Column Indexing
A frequent mistake is mixing up how to access row elements versus column elements. When comparing row i
with column j
, developers often write:
- Wrong:
grid[k][i]
for row elements orgrid[j][k]
for column elements - Correct:
grid[i][k]
for the k-th element of rowi
andgrid[k][j]
for the k-th element of columnj
Solution: Remember that in a 2D array grid[row][col]
, the first index is always the row. So for row i
, iterate through columns with grid[i][k]
, and for column j
, iterate through rows with grid[k][j]
.
2. Inefficient String/Tuple Comparison Approach
Some developers convert rows and columns to strings or tuples for comparison:
# Inefficient approach
for i in range(n):
row = str(grid[i]) # or tuple(grid[i])
for j in range(n):
col = str([grid[k][j] for k in range(n)])
if row == col:
pair_count += 1
This creates unnecessary objects and can be slower, especially with large matrices.
Solution: Stick with element-by-element comparison using the generator expression with all()
. It's more memory-efficient and stops early if a mismatch is found.
3. Not Handling Edge Cases
Forgetting to consider:
- Empty grid (
n = 0
) - Single element grid (
n = 1
) - Grids with duplicate values that might cause counting errors
Solution: The current implementation naturally handles these cases, but always verify:
- A 1×1 grid correctly returns 1 (the single row equals the single column)
- Empty grids are typically not given in this problem, but checking
if not grid
at the start can prevent errors
4. Attempting Optimization with Hashing Without Considering Order
Some might try to optimize by hashing rows and columns:
# Wrong optimization attempt
row_set = {frozenset(row) for row in grid}
col_set = {frozenset(grid[k][j] for k in range(n)) for j in range(n)}
This fails because sets don't preserve order, and the problem requires exact order matching.
Solution: If optimizing with hashing, use tuples instead of sets to preserve order:
from collections import Counter
n = len(grid)
rows = Counter(tuple(row) for row in grid)
cols = Counter(tuple(grid[i][j] for i in range(n)) for j in range(n))
return sum(rows[key] * cols[key] for key in rows if key in cols)
Which data structure is used in a depth first search?
Recommended Readings
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 assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!