- 科学计算
【免费下载链接】codeforces-go
算法竞赛模板库 by 灵茶山艾府 💭💡🎈
本篇文章围绕 LeetCode 双周赛 130 第一题的题解文档 展开,完整讲解「检查矩阵是否满足条件(Check if Grid Satisfies Conditions)」的判定规则、逐格遍历解法与复杂度分析,并结合 codeforces-go 仓库中的 Go 实现、自动测试用例 与 测试数据文件,从题目思路到仓库级验证流程做一次完整剖析。读完本文,你将掌握此类「逐格校验二维数组约束」题目的通用判定套路,也能理解该仓库如何用反射驱动的方式对题解函数做批量自动化验证。
一、题目与判定规则
给定一个m × n的二维整数矩阵grid,要求判断它是否满足如下两条同时成立的条件:
- 同行相邻相等:对每个格子
grid[i][j](j > 0),必须满足grid[i][j] == grid[i][j-1],即同一行内相邻元素相等;等价地,整个矩阵的每一行内部所有元素都相同。 - 同列相邻相等:对每个格子
grid[i][j](i > 0),必须满足grid[i][j] == grid[i-1][j],即当前格与上一行同列格子相等;等价地,整个矩阵的每一列内部所有元素都相同。
把两条规则合在一起看,本质上是:矩阵必须满足「每行元素一致、每列元素一致」,即任意两个格子只要位于同一行或同一列,其值就必然相同。满足条件则返回true,否则返回false。
二、解法:逐格遍历,条件不满足立即返回
题解思路非常直接——遍历矩阵,对每个grid[i][j]挨个判断:
- 如果
j > 0且grid[i][j] == grid[i][j-1],说明同一行相邻两个元素相等,违反了「同行相邻相等」的约束,返回false。 - 如果
i > 0且grid[i][j] != grid[i-1][j],说明当前格与上一行同列元素不相等,违反了「同列相邻相等」的约束,返回false。 - 如果整个遍历过程中都没有返回
false,最后返回true。
这种做法的关键是一旦发现违规立即返回,无需检查完整个矩阵,天然带有短路效果。由于条件 1 要求同行元素全部相同,条件 2 要求同列元素全部相同,逐格只与「左侧格」和「上方格」比较即可覆盖全部约束,无需回溯或重复判断。
各语言参考实现
题解文档给出了 Python3、Java、C++、Go 四种语言的完整实现:
class Solution: def satisfiesConditions(self, grid: List[List[int]]) -> bool: for i, row in enumerate(grid): for j, x in enumerate(row): if j and x == row[j - 1] or i and x != grid[i - 1][j]: return False return Trueclass Solution { public boolean satisfiesConditions(int[][] grid) { for (int i = 0; i < grid.length; i++) { for (int j = 0; j < grid[i].length; j++) { if (j > 0 && grid[i][j] == grid[i][j - 1] || i > 0 && grid[i][j] != grid[i - 1][j]) { return false; } } } return true; } }class Solution { public: bool satisfiesConditions(vector<vector<int>>& grid) { for (int i = 0; i < grid.size(); i++) { for (int j = 0; j < grid[i].size(); j++) { if (j && grid[i][j] == grid[i][j - 1] || i && grid[i][j] != grid[i - 1][j]) { return false; } } } return true; } };func satisfiesConditions(grid [][]int) bool { for i, row := range grid { for j, x := range row { if j > 0 && x == row[j-1] || i > 0 && x != grid[i-1][j] { return false } } } return true }需要注意的是,题解代码中「同行相邻」的检查条件是x == row[j-1](相等即违规),而「同列相邻」的检查条件是x != grid[i-1][j](不相等即违规)。两个条件使用不同的比较方向:前者要求同行元素相等、违者返回false;后者要求同列元素相等、违者返回false。这是因为本题两条约束分别是「同行必须相等」和「同列必须相等」,不要想当然地把两个条件写成相同形式。
复杂度分析
- 时间复杂度:
O(mn),其中m和n分别为grid的行数和列数。每个格子至多被检查一次,且在发现首个违规格时提前终止。 - 空间复杂度:
O(1),除若干临时变量外不申请额外空间,不依赖矩阵规模。
三、仓库源码视角:从题解到可验证的 Go 实现
题解文档 中的 Go 参考实现与仓库内实际提交的 a.go 完全一致。仓库将每个双周赛/周赛题目独立组织为一个目录,本题位于leetcode/biweekly/130/a/目录下,目录中除题解文档外还包含:
- a.go:独立于 LeetCode 平台的 Go 实现,函数签名与题解一致,可脱离平台直接运行验证;
- a_test.go:由模板自动生成的测试文件;
- a.txt:纯文本测试用例数据。
这种「题解 + 实现 + 测试 + 数据」四件套的组织方式,是 codeforces-go 仓库对每一道题目的标准布局,方便读者把题解中的思路直接映射为可编译、可测试的真实代码。
四、自动化验证:测试驱动如何保证题解正确
测试文件 的头部注释标明它由copypasta/template/leetcode/generator_test.go自动生成,测试核心只有一段:
func Test_a(t *testing.T) { if err := testutil.RunLeetCodeFuncWithFile(t, satisfiesConditions, "a.txt", 0); err != nil { t.Fatal(err) } }关键在testutil.RunLeetCodeFuncWithFile这个统一入口(实现在 leetcode/testutil/leetcode.go):
- 读取
a.txt中的全部用例数据; - 根据目标函数的反射类型(
fType.NumIn()与fType.NumOut())确定每个用例由几行数据构成,将文本按固定间隔切分成examples; - 对每个用例,通过
parseRawArg把原始文本解析成 Go 值(如[][]int),调用函数后经toRawString序列化输出,并与期望结果比较; - 若
targetCaseNum为 0,则跑完全部用例;若为正数则只跑指定用例;为负数则映射到最后一个用例。
这套机制使得只要把用例按「输入行、输出行」格式写进a.txt,任意题解函数都能被自动批量验证,同时支持用例级别的超时检测(isTLE)与单用例调试,是仓库「写一题、验一题」流水线的核心支撑。
五、用例数据与逐例推演
测试数据文件 中共包含三组用例(每组由 1 行矩阵输入 + 1 行期望输出组成):
[[1,0,2],[1,0,2]] true [[1,1,1],[0,0,0]] false [[1],[2],[3]] false逐例推演如下:
[[1,0,2],[1,0,2]]→true:第一行[1,0,2]与第二行[1,0,2]完全相同,同行元素相等、同列元素也相等,两条约束都满足,判定为true。[[1,1,1],[0,0,0]]→false:第一行内部元素全为 1,第二行内部全为 0,满足同行约束;但第 0 列元素1 != 0、第 1 列1 != 0、第 2 列1 != 0,同列约束全部违反,判定为false。[[1],[2],[3]]→false:矩阵只有一列,列内元素1 != 2 != 3,违反同列约束,判定为false。
这三组用例恰好覆盖了「完全满足」「同行满足但同列不满足」「单列违反」三种典型形态,作为本题的正反向验证样本非常精简有效。
六、小结:一类「逐格校验」题的通用方法论
通过本题可以提炼出一个适用于大量二维数组约束判定题的通用套路:
- 提炼约束:先把题目文字描述的约束转成「对每个格子、相对某个邻格」的逐格判定条件,并注意每条约束的比较方向与违规条件;
- 最小比较集:多数约束只需与「左侧 / 上方 / 右侧 / 下方」中的一个邻格比较即可传递覆盖全局,不必做全局两两比较;
- 短路返回:一旦发现首个违规格立即返回
false,既正确又高效; - 复杂度锚定:
O(mn)时间、O(1)空间的解法通常是此类题目的标准答案,可直接对照题解中的复杂度分析核对。
本题在双周赛 130 中作为第一题(A 题)出现,是典型的「签到级」实现题,但它的逐格判定框架同样适用于网格图 DFS/BFS、二维前缀和校验等更复杂场景。读者可以结合 a.go 的完整实现、a_test.go 的测试入口以及 testutil/leetcode.go 的测试框架源码,在自己本地环境完成一次「读题解 → 跑用例 → 改数据再验证」的完整闭环,从而真正吃透这一题型。
- 科学计算
【免费下载链接】codeforces-go
算法竞赛模板库 by 灵茶山艾府 💭💡🎈
相关推荐
codeforces-go 仓库题解精读:LeetCode 双周赛 104 第 2 题"矩阵求和"(Sum in a Matrix)的排序贪心解法
codeforces go 仓库题解精读:LeetCode 双周赛 104 第 2 题"矩阵求和"(Sum in a Matrix)的排序贪心解法 导读 本文基
科学计算codeforces-go 题解精讲:LeetCode 双周赛 122 第三题 Minimum Length of Array Using Operations 的取模操作推演与最短化证明
codeforces go 题解精讲:LeetCode 双周赛 122 第三题 Minimum Length of Array Using Operations
科学计算codeforces-go 题解精讲:双指针 + 循环递增判定子序列(力扣第 111 场双周赛 T2)
codeforces go 题解精讲:双指针 + 循环递增判定子序列(力扣第 111 场双周赛 T2) 本文围绕算法竞赛模板库 codeforces go 中
科学计算
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考