问题描述
小B最近迷上了艺术创作,他正在设计一个由字母O组成的图案。为了绘制这个图案,他需要在一张网格纸上标记出O的位置。但是小B发现,如果直接绘制所有的O,图案会显得杂乱无章。于是他想到一个办法:只绘制那些所在行和所在列中O的个数均为偶数的O,这样图案会更加平衡和和谐。
给定一个 n x n 的网格,每个格子可能是空的(用0表示)或者包含一个O(用1表示)。小B请求你帮助他找出所有需要绘制的O的位置,即那些同时满足以下条件的格子:
- 格子中包含O(值为1)
- 该格子所在行中O的总个数为偶数
- 该格子所在列中O的总个数为偶数
要求:
- 设计一个算法,遍历网格一次,找出所有满足条件的格子坐标。
- 算法的时间复杂度应为 O(n^2),其中 n 是网格的大小。
- 尽量减少额外空间的使用,以优化算法效率。
测试样例
样例1:
输入:
grid = [[1,0,1],[0,1,0],[1,0,1]]输出:[[0,0],[0,2],[2,0],[2,2]]解释:网格中四个角上的格子包含O(值为1)。第一行有2个O(偶数),第一列有2个O(偶数);第三行有2个O(偶数),第三列有2个O(偶数)。因此这四个格子满足条件。中心格子1,1虽然包含O,但其所在行有1个O(奇数),所在列有1个O(奇数),因此不满足条件。
样例2:
输入:
grid = [[0,1,0],[1,1,1],[0,1,0]]输出:[]解释:所有包含O的格子中,第一行有1个O(奇数),第二行有3个O(奇数),第三行有1个O(奇数);第一列有1个O(奇数),第二列有3个O(奇数),第三列有1个O(奇数)。没有任何格子同时满足行和列O个数均为偶数的条件。
样例3:
输入:
grid = [[1,1],[1,1]]输出:[[0,0],[0,1],[1,0],[1,1]]解释:所有格子都包含O。每行都有2个O(偶数),每列都有2个O(偶数),因此所有格子都满足条件。
样例4:
输入:
grid = [[1]]输出:[]解释:唯一格子包含O,但其所在行有1个O(奇数),所在列有1个O(奇数),因此不满足条件。
约束条件
- 网格大小 n 满足 1 ≤ n ≤ 100
- 网格中的值只能是0或1
解题思路
要解决这个问题,我们需要找出所有同时满足以下条件的格子:
- 格子值为1(包含O)
- 该格子所在行的O总数为偶数
- 该格子所在列的O总数为偶数
高效的做法是:
- 首先预处理每行和每列的O个数,计算它们的奇偶性
- 然后遍历每个格子,检查是否同时满足三个条件
具体步骤:
- 创建两个数组
rowParity和colParity,长度均为 n rowParity[i]表示第 i 行中O个数的奇偶性(0表示偶数,1表示奇数)colParity[j]表示第 j 列中O个数的奇偶性(0表示偶数,1表示奇数)- 遍历网格,统计每行每列的O个数并计算奇偶性
- 再次遍历网格,对于每个格子
grid[i][j]:- 如果
grid[i][j] == 1(包含O) - 且
rowParity[i] == 0(行O个数为偶数) - 且
colParity[j] == 0(列O个数为偶数) - 则将该格子的坐标
[i, j]加入结果列表
- 如果
这种方法的时间复杂度为 O(n²),空间复杂度为 O(n),满足题目要求。
程序代码
#include <stdio.h>
#include <stdlib.h>
int** findValidO(int** grid, int gridSize, int* gridColSize, int* returnSize, int** returnColumnSizes) {
int n = gridSize;
// 统计每行、每列的1的个数奇偶性
int* rowParity = (int*)calloc(n, sizeof(int));
int* colParity = (int*)calloc(n, sizeof(int));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (gridij == 1) {
rowParityi ^= 1;
colParityj ^= 1;
}
}
}
// 分配结果空间
int** result = (int**)malloc(n * n * sizeof(int*));
int* colSizes = (int*)malloc(n * n * sizeof(int));
int idx = 0;
// 筛选
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (gridij == 1 && rowParityi == 0 && colParityj == 0) {
resultidx = (int*)malloc(2 * sizeof(int));
resultidx0 = i;
resultidx1 = j;
colSizesidx = 2;
idx++;
}
}
}
*returnSize = idx;
*returnColumnSizes = colSizes;
free(rowParity);
free(colParity);
return result;
}
int main() {
// 测试样例1
int grid1Data33 = {{1,0,1},{0,1,0},{1,0,1}};
int* grid13 = {grid1Data0, grid1Data1, grid1Data2};
int gridColSize13 = {3, 3, 3};
int returnSize1;
int* returnColumnSizes1;
int** result1 = findValidO(grid1, 3, gridColSize1, &returnSize1, &returnColumnSizes1);
printf("[");
for (int i = 0; i < returnSize1; i++) {
printf("%d,%d", result1i0, result1i1);
if (i < returnSize1 - 1) printf(",");
}
printf("]\n");
// 测试样例2
int grid2Data33 = {{0,1,0},{1,1,1},{0,1,0}};
int* grid23 = {grid2Data0, grid2Data1, grid2Data2};
int gridColSize23 = {3, 3, 3};
int returnSize2;
int* returnColumnSizes2;
int** result2 = findValidO(grid2, 3, gridColSize2, &returnSize2, &returnColumnSizes2);
printf("[");
for (int i = 0; i < returnSize2; i++) {
printf("%d,%d", result2i0, result2i1);
if (i < returnSize2 - 1) printf(",");
}
printf("]\n");
// 测试样例3
int grid3Data22 = {{1,1},{1,1}};
int* grid32 = {grid3Data0, grid3Data1};
int gridColSize32 = {2, 2};
int returnSize3;
int* returnColumnSizes3;
int** result3 = findValidO(grid3, 2, gridColSize3, &returnSize3, &returnColumnSizes3);
printf("[");
for (int i = 0; i < returnSize3; i++) {
printf("%d,%d", result3i0, result3i1);
if (i < returnSize3 - 1) printf(",");
}
printf("]\n");
// 测试样例4
int grid4Data11 = {{1}};
int* grid41 = {grid4Data0};
int gridColSize41 = {1};
int returnSize4;
int* returnColumnSizes4;
int** result4 = findValidO(grid4, 1, gridColSize4, &returnSize4, &returnColumnSizes4);
printf("[");
for (int i = 0; i < returnSize4; i++) {
printf("%d,%d", result4i0, result4i1);
if (i < returnSize4 - 1) printf(",");
}
printf("]\n");
return 0;
}
cpp
#include <stdio.h>
#include <stdlib.h>
int** findValidO(int** grid, int gridSize, int* gridColSize, int* returnSize, int** returnColumnSizes) {
int n = gridSize;
// 统计每行、每列的1的个数奇偶性
int* rowParity = (int*)calloc(n, sizeof(int));
int* colParity = (int*)calloc(n, sizeof(int));
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
rowParity[i] ^= 1;
colParity[j] ^= 1;
}
}
}
// 分配结果空间
int** result = (int**)malloc(n * n * sizeof(int*));
int* colSizes = (int*)malloc(n * n * sizeof(int));
int idx = 0;
// 筛选
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1 && rowParity[i] == 0 && colParity[j] == 0) {
result[idx] = (int*)malloc(2 * sizeof(int));
result[idx][0] = i;
result[idx][1] = j;
colSizes[idx] = 2;
idx++;
}
}
}
*returnSize = idx;
*returnColumnSizes = colSizes;
free(rowParity);
free(colParity);
return result;
}
int main() {
// 测试样例1
int grid1Data[3][3] = {{1,0,1},{0,1,0},{1,0,1}};
int* grid1[3] = {grid1Data[0], grid1Data[1], grid1Data[2]};
int gridColSize1[3] = {3, 3, 3};
int returnSize1;
int* returnColumnSizes1;
int** result1 = findValidO(grid1, 3, gridColSize1, &returnSize1, &returnColumnSizes1);
printf("[");
for (int i = 0; i < returnSize1; i++) {
printf("[%d,%d]", result1[i][0], result1[i][1]);
if (i < returnSize1 - 1) printf(",");
}
printf("]\n");
// 测试样例2
int grid2Data[3][3] = {{0,1,0},{1,1,1},{0,1,0}};
int* grid2[3] = {grid2Data[0], grid2Data[1], grid2Data[2]};
int gridColSize2[3] = {3, 3, 3};
int returnSize2;
int* returnColumnSizes2;
int** result2 = findValidO(grid2, 3, gridColSize2, &returnSize2, &returnColumnSizes2);
printf("[");
for (int i = 0; i < returnSize2; i++) {
printf("[%d,%d]", result2[i][0], result2[i][1]);
if (i < returnSize2 - 1) printf(",");
}
printf("]\n");
// 测试样例3
int grid3Data[2][2] = {{1,1},{1,1}};
int* grid3[2] = {grid3Data[0], grid3Data[1]};
int gridColSize3[2] = {2, 2};
int returnSize3;
int* returnColumnSizes3;
int** result3 = findValidO(grid3, 2, gridColSize3, &returnSize3, &returnColumnSizes3);
printf("[");
for (int i = 0; i < returnSize3; i++) {
printf("[%d,%d]", result3[i][0], result3[i][1]);
if (i < returnSize3 - 1) printf(",");
}
printf("]\n");
// 测试样例4
int grid4Data[1][1] = {{1}};
int* grid4[1] = {grid4Data[0]};
int gridColSize4[1] = {1};
int returnSize4;
int* returnColumnSizes4;
int** result4 = findValidO(grid4, 1, gridColSize4, &returnSize4, &returnColumnSizes4);
printf("[");
for (int i = 0; i < returnSize4; i++) {
printf("[%d,%d]", result4[i][0], result4[i][1]);
if (i < returnSize4 - 1) printf(",");
}
printf("]\n");
return 0;
}
运行结果
