LeetCode 2352: Equal Row and Column Pairs (Row Signature Counting)
LeetCode 2352MatrixHash MapToday we solve LeetCode 2352 - Equal Row and Column Pairs.
Source: https://leetcode.com/problems/equal-row-and-column-pairs/
English
Problem Summary
Given an n x n matrix, count pairs (ri, cj) where row ri and column cj are identical element by element.
Key Insight
Convert each row into a signature string and count frequencies in a hash map. Then build each column signature and add the matching row count from the map.
Algorithm
- Build rowCount[signature] for all rows.
- For each column, build its signature.
- Add rowCount[columnSignature] to the answer.
Complexity Analysis
Time: O(n^2).
Space: O(n^2) for stored row signatures.
Common Pitfalls
- Using ambiguous signatures without separators (e.g. 1,11 vs 11,1).
- Forgetting duplicate rows should contribute multiple matches.
- Rebuilding rows for each column (wastes time).
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public int equalPairs(int[][] grid) {
int n = grid.length;
Map<String, Integer> rowCount = new HashMap<>();
for (int i = 0; i < n; i++) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < n; j++) sb.append(grid[i][j]).append('#');
String key = sb.toString();
rowCount.put(key, rowCount.getOrDefault(key, 0) + 1);
}
int ans = 0;
for (int j = 0; j < n; j++) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) sb.append(grid[i][j]).append('#');
ans += rowCount.getOrDefault(sb.toString(), 0);
}
return ans;
}
}func equalPairs(grid [][]int) int {
n := len(grid)
rowCount := map[string]int{}
for i := 0; i < n; i++ {
b := strings.Builder{}
for j := 0; j < n; j++ {
b.WriteString(strconv.Itoa(grid[i][j]))
b.WriteByte('#')
}
rowCount[b.String()]++
}
ans := 0
for j := 0; j < n; j++ {
b := strings.Builder{}
for i := 0; i < n; i++ {
b.WriteString(strconv.Itoa(grid[i][j]))
b.WriteByte('#')
}
ans += rowCount[b.String()]
}
return ans
}class Solution {
public:
int equalPairs(vector<vector<int>>& grid) {
int n = (int)grid.size();
unordered_map<string, int> rowCount;
for (int i = 0; i < n; i++) {
string key;
for (int j = 0; j < n; j++) {
key += to_string(grid[i][j]);
key.push_back('#');
}
rowCount[key]++;
}
int ans = 0;
for (int j = 0; j < n; j++) {
string key;
for (int i = 0; i < n; i++) {
key += to_string(grid[i][j]);
key.push_back('#');
}
ans += rowCount[key];
}
return ans;
}
};class Solution:
def equalPairs(self, grid: list[list[int]]) -> int:
n = len(grid)
row_count = {}
for row in grid:
key = '#'.join(map(str, row)) + '#'
row_count[key] = row_count.get(key, 0) + 1
ans = 0
for j in range(n):
key = '#'.join(str(grid[i][j]) for i in range(n)) + '#'
ans += row_count.get(key, 0)
return ansvar equalPairs = function(grid) {
const n = grid.length;
const rowCount = new Map();
for (let i = 0; i < n; i++) {
let key = "";
for (let j = 0; j < n; j++) key += grid[i][j] + "#";
rowCount.set(key, (rowCount.get(key) || 0) + 1);
}
let ans = 0;
for (let j = 0; j < n; j++) {
let key = "";
for (let i = 0; i < n; i++) key += grid[i][j] + "#";
ans += rowCount.get(key) || 0;
}
return ans;
};中文
题目概述
给定一个 n x n 矩阵,统计有多少对 (ri, cj) 满足第 ri 行与第 cj 列逐项完全相同。
核心思路
先把每一行编码成带分隔符的签名字符串,用哈希表统计行签名出现次数。再逐列构造签名,直接在哈希表里查询并累加次数。
算法步骤
- 遍历所有行,构造签名并写入 rowCount。
- 遍历所有列,构造列签名。
- 把 rowCount[colSignature] 累加到答案。
复杂度分析
时间复杂度:O(n^2)。
空间复杂度:O(n^2)(存储所有行签名)。
常见陷阱
- 签名没有分隔符会产生歧义。
- 忽略重复行的频次,导致少算。
- 每次比较都现算整行整列,造成不必要重复计算。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public int equalPairs(int[][] grid) {
int n = grid.length;
Map<String, Integer> rowCount = new HashMap<>();
for (int i = 0; i < n; i++) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < n; j++) sb.append(grid[i][j]).append('#');
String key = sb.toString();
rowCount.put(key, rowCount.getOrDefault(key, 0) + 1);
}
int ans = 0;
for (int j = 0; j < n; j++) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; i++) sb.append(grid[i][j]).append('#');
ans += rowCount.getOrDefault(sb.toString(), 0);
}
return ans;
}
}func equalPairs(grid [][]int) int {
n := len(grid)
rowCount := map[string]int{}
for i := 0; i < n; i++ {
b := strings.Builder{}
for j := 0; j < n; j++ {
b.WriteString(strconv.Itoa(grid[i][j]))
b.WriteByte('#')
}
rowCount[b.String()]++
}
ans := 0
for j := 0; j < n; j++ {
b := strings.Builder{}
for i := 0; i < n; i++ {
b.WriteString(strconv.Itoa(grid[i][j]))
b.WriteByte('#')
}
ans += rowCount[b.String()]
}
return ans
}class Solution {
public:
int equalPairs(vector<vector<int>>& grid) {
int n = (int)grid.size();
unordered_map<string, int> rowCount;
for (int i = 0; i < n; i++) {
string key;
for (int j = 0; j < n; j++) {
key += to_string(grid[i][j]);
key.push_back('#');
}
rowCount[key]++;
}
int ans = 0;
for (int j = 0; j < n; j++) {
string key;
for (int i = 0; i < n; i++) {
key += to_string(grid[i][j]);
key.push_back('#');
}
ans += rowCount[key];
}
return ans;
}
};class Solution:
def equalPairs(self, grid: list[list[int]]) -> int:
n = len(grid)
row_count = {}
for row in grid:
key = '#'.join(map(str, row)) + '#'
row_count[key] = row_count.get(key, 0) + 1
ans = 0
for j in range(n):
key = '#'.join(str(grid[i][j]) for i in range(n)) + '#'
ans += row_count.get(key, 0)
return ansvar equalPairs = function(grid) {
const n = grid.length;
const rowCount = new Map();
for (let i = 0; i < n; i++) {
let key = "";
for (let j = 0; j < n; j++) key += grid[i][j] + "#";
rowCount.set(key, (rowCount.get(key) || 0) + 1);
}
let ans = 0;
for (let j = 0; j < n; j++) {
let key = "";
for (let i = 0; i < n; i++) key += grid[i][j] + "#";
ans += rowCount.get(key) || 0;
}
return ans;
};
Comments