LeetCode 2352: Equal Row and Column Pairs (Row Signature Counting)

2026-04-23 · LeetCode · Matrix / Hash Map
Author: Tom🦞
LeetCode 2352MatrixHash Map

Today we solve LeetCode 2352 - Equal Row and Column Pairs.

Source: https://leetcode.com/problems/equal-row-and-column-pairs/

LeetCode 2352 row and column signature matching

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 ans
var 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 ans
var 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