C语言/数据结构二维数组题解:找出行列O个数均为偶数的格子——奇偶性预处理+二次遍历

问题描述

小B最近迷上了艺术创作,他正在设计一个由字母O组成的图案。为了绘制这个图案,他需要在一张网格纸上标记出O的位置。但是小B发现,如果直接绘制所有的O,图案会显得杂乱无章。于是他想到一个办法:只绘制那些所在行和所在列中O的个数均为偶数的O,这样图案会更加平衡和和谐。

给定一个 n x n 的网格,每个格子可能是空的(用0表示)或者包含一个O(用1表示)。小B请求你帮助他找出所有需要绘制的O的位置,即那些同时满足以下条件的格子:

  1. 格子中包含O(值为1)
  2. 该格子所在行中O的总个数为偶数
  3. 该格子所在列中O的总个数为偶数

要求:

  1. 设计一个算法,遍历网格一次,找出所有满足条件的格子坐标。
  2. 算法的时间复杂度应为 O(n^2),其中 n 是网格的大小。
  3. 尽量减少额外空间的使用,以优化算法效率。

测试样例

样例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. 格子值为1(包含O)
  2. 该格子所在行的O总数为偶数
  3. 该格子所在列的O总数为偶数

高效的做法是:

  1. 首先预处理每行和每列的O个数,计算它们的奇偶性
  2. 然后遍历每个格子,检查是否同时满足三个条件

具体步骤:

  • 创建两个数组 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;
}

运行结果

相关推荐
程序猿阿森1 小时前
【机器学习实战】朴素贝叶斯算法详解:从概率基础到商品评论情感分析
算法·机器学习·概率论
xxwl5851 小时前
区域赛算法模版第五章---数学与数论
c++·笔记·算法
看浪的路人2 小时前
第6讲:Agent 安全体系——Prompt 注入防御、工具调用审计与输出合规
人工智能·算法
局部有解2 小时前
LeetCode Hot100 438 找到字符串中所有字母异位词
c++·算法·leetcode
垆边人似月.2 小时前
移动长度 k 子串使字符串变成回文
数据结构·算法
David猪大卫2 小时前
【C++修炼】string类:string类的模拟实现
c语言·开发语言·数据结构·c++·经验分享·笔记·学习
pride.li2 小时前
第12章 Python 教程-流程控制:循环结构
linux·服务器·python·算法
Lxx_Zw2 小时前
先把轮子转稳,才不会烧心:编码器速度环 PID 怎么接回 PWM
c语言·stm32·单片机·嵌入式硬件
头像很酷2 小时前
嵌入式虚拟化-xvisor-物理内存大管家
c语言·hypervisor·xvisor·嵌入式虚拟化