Medium
题目描述
给定一个二维字符矩阵 grid,其中 grid[i][j] 是 ‘X’、‘Y’ 或 ‘.’ 中的一个,返回满足以下条件的子矩阵数量:
- 包含
grid[0][0] - ‘X’ 和 ‘Y’ 的频率相等
- 至少包含一个 ‘X’
示例 1:
输入:grid = [["X","Y","."],["Y",".","."]]
输出:3
示例 2:
输入:grid = [["X","X"],["X","Y"]]
输出:0
解释:没有子矩阵具有相等的 'X' 和 'Y' 频率。
示例 3:
输入:grid = [[".","."],[".","."]]
输出:0
解释:没有子矩阵至少包含一个 'X'。
约束条件:
1 <= grid.length, grid[i].length <= 1000grid[i][j]是 ‘X’、‘Y’ 或 ‘.’ 中的一个
提示:
- 将 ‘X’ 替换为 1,‘Y’ 替换为 -1,’.’ 替换为 0
- 需要找到多少个从
grid[0][0]开始的子矩阵grid[0..x][0..y]的和为 0 且至少包含一个 ‘X’ - 使用前缀和来计算子矩阵的和
解题思路
这是一个巧妙的前缀和问题。根据题目提示,我们可以将问题转化:
核心思路:
- 数值映射:将 ‘X’ 映射为 1,‘Y’ 映射为 -1,’.’ 映射为 0
- 问题转化:寻找从
grid[0][0]开始的子矩阵,使得矩阵和为 0(即 X 和 Y 数量相等)且至少包含一个 X
算法步骤:
- 构建二维前缀和数组,同时记录 X 的数量
- 遍历所有可能的右下角位置
(i,j) - 对每个位置,检查从
(0,0)到(i,j)的子矩阵是否满足条件:- 前缀和为 0(X 和 Y 数量相等)
- X 的数量大于 0(至少有一个 X)
优化要点:
- 使用前缀和避免重复计算
- 同时维护数值前缀和(用于判断 X、Y 是否相等)和 X 数量前缀和(用于判断是否有 X)
时间复杂度为 O(m×n),空间复杂度为 O(m×n),其中 m 和 n 分别为矩阵的行数和列数。
代码实现
class Solution {
public:
int numberOfSubmatrices(vector<vector<char>>& grid) {
int m = grid.size();
int n = grid[0].size();
// 前缀和数组:prefixSum[i][j] 表示从(0,0)到(i,j)的数值和
// prefixX[i][j] 表示从(0,0)到(i,j)的X的数量
vector<vector<int>> prefixSum(m + 1, vector<int>(n + 1, 0));
vector<vector<int>> prefixX(m + 1, vector<int>(n + 1, 0));
int result = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
int val = 0, xCount = 0;
if (grid[i-1][j-1] == 'X') {
val = 1;
xCount = 1;
} else if (grid[i-1][j-1] == 'Y') {
val = -1;
}
prefixSum[i][j] = prefixSum[i-1][j] + prefixSum[i][j-1]
- prefixSum[i-1][j-1] + val;
prefixX[i][j] = prefixX[i-1][j] + prefixX[i][j-1]
- prefixX[i-1][j-1] + xCount;
// 检查从(0,0)到(i-1,j-1)的子矩阵
if (prefixSum[i][j] == 0 && prefixX[i][j] > 0) {
result++;
}
}
}
return result;
}
};
class Solution:
def numberOfSubmatrices(self, grid: List[List[str]]) -> int:
m, n = len(grid), len(grid[0])
# 前缀和数组
prefix_sum = [[0] * (n + 1) for _ in range(m + 1)]
prefix_x = [[0] * (n + 1) for _ in range(m + 1)]
result = 0
for i in range(1, m + 1):
for j in range(1, n + 1):
val = 0
x_count = 0
if grid[i-1][j-1] == 'X':
val = 1
x_count = 1
elif grid[i-1][j-1] == 'Y':
val = -1
prefix_sum[i][j] = (prefix_sum[i-1][j] + prefix_sum[i][j-1]
- prefix_sum[i-1][j-1] + val)
prefix_x[i][j] = (prefix_x[i-1][j] + prefix_x[i][j-1]
- prefix_x[i-1][j-1] + x_count)
# 检查从(0,0)到(i-1,j-1)的子矩阵
if prefix_sum[i][j] == 0 and prefix_x[i][j] > 0:
result += 1
return result
public class Solution {
public int NumberOfSubmatrices(char[][] grid) {
int m = grid.Length;
int n = grid[0].Length;
// 前缀和数组
int[,] prefixSum = new int[m + 1, n + 1];
int[,] prefixX = new int[m + 1, n + 1];
int result = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
int val = 0, xCount = 0;
if (grid[i-1][j-1] == 'X') {
val = 1;
xCount = 1;
} else if (grid[i-1][j-1] == 'Y') {
val = -1;
}
prefixSum[i, j] = prefixSum[i-1, j] + prefixSum[i, j-1]
- prefixSum[i-1, j-1] + val;
prefixX[i, j] = prefixX[i-1, j] + prefixX[i, j-1]
- prefixX[i-1, j-1] + xCount;
// 检查从(0,0)到(i-1,j-1)的子矩阵
if (prefixSum[i, j] == 0 && prefixX[i, j] > 0) {
result++;
}
}
}
return result;
}
}
var numberOfSubmatrices = function(grid) {
const m = grid.length;
const n = grid[0].length;
let count = 0;
// Prefix sum arrays for X and Y counts
const prefixX = Array(m + 1).fill().map(() => Array(n + 1).fill(0));
const prefixY = Array(m + 1).fill().map(() => Array(n + 1).fill(0));
// Build prefix sum arrays
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
prefixX[i][j] = prefixX[i-1][j] + prefixX[i][j-1] - prefixX[i-1][j-1];
prefixY[i][j] = prefixY[i-1][j] + prefixY[i][j-1] - prefixY[i-1][j-1];
if (grid[i-1][j-1] === 'X') {
prefixX[i][j]++;
} else if (grid[i-1][j-1] === 'Y') {
prefixY[i][j]++;
}
}
}
// Check all submatrices starting from (0,0)
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
const xCount = prefixX[i][j];
const yCount = prefixY[i][j];
if (xCount > 0 && xCount === yCount) {
count++;
}
}
}
return count;
};
复杂度分析
| 复杂度类型 | 复杂度 | 说明 |
|---|---|---|
| 时间复杂度 | O(m×n) | 需要遍历整个矩阵一次,每个位置的计算都是 O(1) |
| 空间复杂度 | O(m×n) | 需要两个大小为 (m+1)×(n+1) 的前缀和数组 |
相关题目
. Maximum Equal Frequency (Hard)
. Count Submatrices With All Ones (Medium)