LeetCode-Go 题解:1252. Cells with Odd Values in a Matrix(奇数值单元格计数)双解法剖析
2026/9/13 0:01:42 网站建设 项目流程

LeetCode-Go 题解:1252. Cells with Odd Values in a Matrix(奇数值单元格计数)双解法剖析

【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go

LeetCode 1252 题要求在一个初始全 0 的 n×m 矩阵上,按给定的行列索引逐一累加,最终统计值为奇数的单元格数量。本文以 LeetCode-Go 仓库中 1252 题 README 为主体,结合仓库内 官方解法源码 与 单元测试,讲解「全矩阵模拟」与「行列计数 + 奇偶性判定」两种思路,帮助你同时掌握暴力模拟与数学推导两类解题能力。

题目回顾:中英对照与核心题意

题目(英文原题)

Givennandmwhich are the dimensions of a matrix initialized by zeros and given an arrayindiceswhereindices[i] = [ri, ci]. For each pair of[ri, ci]you have to increment all cells in rowriand columnciby 1.

Returnthe number of cells with odd valuesin the matrix after applying the increment to allindices.

题目大意(中文解读)

给你一个 n 行 m 列的矩阵,最开始的时候,每个单元格中的值都是 0。另有一个索引数组indicesindices[i] = [ri, ci]中的rici分别表示指定的行和列(从 0 开始编号)。你需要将每对[ri, ci]指定的行和列上的所有单元格的值加 1。请你在执行完所有indices指定的增量操作后,返回矩阵中「奇数值单元格」的数目。

这里有一个容易被忽略的细节:当某一对[ri, ci]执行时,行ri与列ci的交点单元格(ri, ci)会被同时加两次(一次来自整行 +1,一次来自整列 +1),这一点在后续的模拟拆解中会再次印证。

示例与约束条件分析

示例一

Input: n = 2, m = 3, indices = [[0,1],[1,1]] Output: 6 Explanation: Initial matrix = [[0,0,0],[0,0,0]]. After applying first increment it becomes [[1,2,1],[0,1,0]]. The final matrix will be [[1,3,1],[1,3,1]] which contains 6 odd numbers.

最终矩阵[[1,3,1],[1,3,1]]中的 6 个元素全部为奇数,因此输出 6。

示例二

Input: n = 2, m = 2, indices = [[1,1],[0,0]] Output: 0 Explanation: Final matrix = [[2,2],[2,2]]. There is no odd number in the final matrix.

两条索引分别作用后,每个单元格恰好被加了两次(行、列各一次),最终矩阵全部为偶数,因此输出 0。

约束范围

  • 1 <= n <= 50
  • 1 <= m <= 50
  • 1 <= indices.length <= 100
  • 0 <= indices[i][0] < n
  • 0 <= indices[i][1] < m

矩阵尺寸与索引数量都相当小(最大 50×50 与 100 条索引),这意味着即使是最直接的暴力模拟,在时间与空间上也没有任何压力,两种解法都能轻松通过。

解法一:全矩阵模拟(oddCells)

这是 README 中标注的「解法一 暴力法」,思路完全按照题意来:先把矩阵建出来,再逐条索引给整行、整列 +1,最后遍历矩阵统计奇数。

实现思路

  1. make([][]int, n)初始化 n 行矩阵,每行再make([]int, m)开辟 m 个 0 值单元格;
  2. 遍历indices,对每条[ri, ci]
    • 先给第ri行的 m 个单元格各 +1;
    • 再给第ci列的 n 个单元格各 +1;
  3. 遍历整个矩阵,用位运算v&1 == 1判断奇数并累加计数。

仓库源码

仓库中实现位于 1252. Cells with Odd Values in a Matrix.go:

// 解法一 暴力法 func oddCells(n int, m int, indices [][]int) int { matrix, res := make([][]int, n), 0 for i := range matrix { matrix[i] = make([]int, m) } for _, indice := range indices { for i := 0; i < m; i++ { matrix[indice[0]][i]++ } for j := 0; j < n; j++ { matrix[j][indice[1]]++ } } for _, m := range matrix { for _, v := range m { if v&1 == 1 { res++ } } } return res }

执行过程拆解(以示例一为例)

n = 2, m = 3, indices = [[0,1],[1,1]]为例:

  1. 初始矩阵:[[0,0,0],[0,0,0]]
  2. 处理[0,1]:第 0 行全体 +1 得[[1,1,1],[0,0,0]];第 1 列全体 +1 得[[1,2,1],[0,1,0]]。其中交点(0,1)从 0 直接变为 2,印证了「交点被加两次」;
  3. 处理[1,1]:第 1 行全体 +1 得[[1,2,1],[1,2,1]];第 1 列全体 +1 得[[1,3,1],[1,3,1]]
  4. 逐格统计奇数:1,3,1,1,3,1共 6 个,返回 6。

复杂度分析

设索引数量为k = len(indices)

  • 初始化矩阵:O(n·m)
  • 每条索引的行列递增:行需O(m)、列需O(n),合计O(k·(n+m))
  • 最终统计:O(n·m)

时间复杂度O(n·m + k·(n+m))空间复杂度O(n·m)(需要保存整个矩阵)。

解法二:行列增量计数 + 奇偶性判定(oddCells1)

这是 README 中标注的「解法二 暴力法」,但它并不真正去修改矩阵,而是利用了一个关键观察:单元格(i,j)的最终值等于rows[i] + cols[j],其中rows[i]是第 i 行被累加的总次数,cols[j]是第 j 列被累加的总次数。于是奇偶性完全由rows[i] + cols[j]决定,不再需要维护矩阵。

核心观察

  • 一个单元格的值只可能来自「它所在的行被加了若干次」与「它所在的列被加了若干次」两部分之和;
  • 因此先分别统计每行的累加次数rows[i]与每列的累加次数cols[j]
  • 再遍历所有(i,j),只要(rows[i]+cols[j]) % 2 == 1即为奇数单元格。

仓库源码

实现位于 1252. Cells with Odd Values in a Matrix.go:

// 解法二 暴力法 func oddCells1(n int, m int, indices [][]int) int { rows, cols, count := make([]int, n), make([]int, m), 0 for _, pair := range indices { rows[pair[0]]++ cols[pair[1]]++ } for i := 0; i < n; i++ { for j := 0; j < m; j++ { if (rows[i]+cols[j])%2 == 1 { count++ } } } return count }

复杂度分析

k = len(indices)

  • 统计行列次数:O(k)
  • 双重循环判定奇偶:O(n·m)

时间复杂度O(k + n·m)空间复杂度O(n + m)(仅需两个一维数组,相比解法一省去了整个矩阵)。

两解法对比与进一步推导

维度解法一 oddCells解法二 oddCells1
核心思想全矩阵模拟,逐行逐列真实 +1行列次数统计 + 奇偶性推导
时间复杂度O(n·m + k·(n+m))O(k + n·m)
空间复杂度O(n·m)O(n + m)
代码可读性直观、贴近题意略抽象,但更快更省

在本题的约束(n、m ≤ 50,k ≤ 100)下两者差距并不明显,但解法二的空间优势与思路推广价值更值得体会。

奇偶性公式推导(从解法二可进一步推断)

观察解法二中的判定条件(rows[i]+cols[j])%2 == 1,可以进一步推断出:单元格(i,j)为奇数,当且仅当rows[i]cols[j]奇偶性不同(一奇一偶)。因此答案还可以用如下组合计数公式直接算出:

answer = 奇数行数 × 偶数列数 + 偶数行数 × 奇数列数

即先数出rows中有多少奇数行oddRowscols中有多少奇数列oddCols,然后:

answer := oddRows*(m-oddCols) + (n-oddRows)*oddCols

这个公式把统计从O(n·m)进一步降到O(n + m),是解法二思路的自然延伸,也是面试中常见的加分推导(注:该公式为本文基于仓库源码逻辑的推导延伸,仓库中并未包含此实现)。

仓库中的测试与验证

测试用例结构

仓库为本题提供了独立的单元测试,位于 1252. Cells with Odd Values in a Matrix_test.go,其组织方式与 LeetCode-Go 仓库其他题目保持一致:

  • para1252结构体封装输入参数nmindices
  • ans1252结构体封装期望答案one
  • question1252将二者绑定为一条完整用例;
  • Test_Problem1252中内置了题目的两个官方示例用例,并在循环中对oddCells打印输入输出,同时调用oddCells1覆盖第二条实现路径,以便仓库的覆盖率统计覆盖到全部解法。

两个用例分别对应:

{para1252{2, 3, [][]int{{0, 1}, {1, 1}}}, ans1252{6}}, // 示例一 {para1252{2, 2, [][]int{{1, 1}, {0, 0}}}, ans1252{0}}, // 示例二

如何运行测试

仓库根目录的 go.mod 声明了模块名github.com/halfrost/LeetCode-Go与 Go 版本要求(go 1.19),因此在仓库根目录下可直接执行:

# 仅运行本题的测试 go test -v ./leetcode/1252.Cells-with-Odd-Values-in-a-Matrix/ # 运行 leetcode 目录下全部题目的测试并统计覆盖率 go test -covermode=atomic -coverprofile=coverage.txt ./leetcode/...

第二条命令正是仓库根目录 gotest.sh 的核心逻辑:它对./leetcode/...一次性执行带覆盖率收集的测试,产出单一合法的coverage.txt文件,这也是仓库宣称 100% 测试覆盖率的统计基础——每一道题都配有与题目示例对齐的测试用例,本题自然也不例外。

小结

LeetCode 1252 是一道典型的「模拟 + 观察」题:解法一忠实还原题意,适合作为第一直觉的保底方案;解法二通过把矩阵值拆解为「行次数 + 列次数」避免了矩阵的构造与维护,时间与空间双双更优。结合 LeetCode-Go 仓库的 README、双解法源码 与 测试用例,你可以直接运行测试验证两种实现的正确性,并把「奇偶性组合计数」这一推导技巧迁移到其他矩阵类题目中。

【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询