LeetCode-Go 题解 37:Sudoku Solver(数独求解器)DFS 回溯枚举实现详解

发布时间:2026/11/9 6:51:56

LeetCode-Go 题解 37:Sudoku Solver(数独求解器)DFS 回溯枚举实现详解 LeetCode-Go 题解 37Sudoku Solver数独求解器DFS 回溯枚举实现详解【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go本篇技术指南以 LeetCode-Go 仓库中 0037.Sudoku-Solver 题解文档 为骨架结合 核心源码 与 单元测试完整讲解第 37 题「Sudoku Solver」的题目约束、DFS 暴力回溯枚举解法、逐函数代码剖析、正确性验证与复杂度分析。读完本文你将掌握如何在 9x9 棋盘上用 Go 从零实现一个可运行、可测试的数独求解器并理解回溯算法尝试—校验—回退的完整闭环。一、题目编写程序自动填充数独空格第 37 题要求编写一个程序通过填充空格来求解数独谜题。一个合法的数独解必须同时满足以下全部规则数字1-9在每一行只能出现一次数字1-9在每一列只能出现一次数字1-9在每一个以粗实线分隔的3x3宫内只能出现一次。空白格用字符.表示。题目同时给出三条重要约束见 题解文档给定的棋盘只包含数字1-9和字符.可以假定给定的数独谜题有且仅有一个唯一解棋盘大小恒为9x9。输入输出形态函数直接修改传入的[][]byte二维棋盘在.处原地填入答案数字没有返回值。这与 LeetCode 的接口签名func solveSudoku(board [][]byte)保持一致。二、解题思路DFS 暴力回溯枚举数独的规则决定了数字不得重复必须同时作用在三个维度每横行、每竖行、每个 3x3 九宫格。因此最直接、也最可靠的策略就是DFS 暴力回溯枚举思路见 题解文档 的 Solution Approach 一节先扫描棋盘把所有空白格.的位置收集起来得到一个待填充位置的列表从第一个空白格开始依次尝试数字1到9每放入一个数字之前都要在行、列、3x3 宫三处做一次合法性校验全部通过才落子递归进入下一个空白格若某格所有候选数字都无法通过校验则回溯到上一个格子撤销刚才的数字重新填回.换下一个数字继续尝试一旦找到一组完整解不再继续回溯直接返回这是保证性能的关键剪枝。这种遇到死路就回头换一条路的策略本质上就是深度优先搜索加回溯Backtracking。本题要求的唯一解特性使得找到即返回的剪枝完全成立。三、核心源码逐函数剖析仓库中的完整实现位于 37. Sudoku Solver.go共拆分为三个职责清晰的函数solveSudoku入口、putSudoku回溯递归与checkSudoku三路合法性校验。3.1 辅助结构体 positiontype position struct { x int y int }position用于记录一个空白格的行号x与列号y是整个回溯过程的状态载体。3.2 入口函数 solveSudoku收集空白格并启动回溯func solveSudoku(board [][]byte) { pos, find : []position{}, false for i : 0; i len(board); i { for j : 0; j len(board[0]); j { if board[i][j] . { pos append(pos, position{x: i, y: j}) } } } putSudoku(board, pos, 0, find) }入口函数做两件事收集空白格双重循环扫描整个 9x9 棋盘把每个值为.的单元格坐标压入pos切片。这一步决定了后续回溯的推进顺序——按行优先、自左向右逐个填充。启动递归调用putSudoku从pos的索引0第一个空白格开始尝试填数同时传入一个find标志初始为false用于标记是否已经找到完整解。值得注意的一个实现细节board以*[][]byte指针方式传入递归find也以*bool指针传递保证递归各层之间共享同一份棋盘状态与已找到解的标志。3.3 递归函数 putSudoku尝试、落子、回退func putSudoku(board *[][]byte, pos []position, index int, succ *bool) { if *succ true { return } if index len(pos) { *succ true return } for i : 1; i 10; i { if checkSudoku(board, pos[index], i) !*succ { (*board)[pos[index].x][pos[index].y] byte(i) 0 putSudoku(board, pos, index1, succ) if *succ true { return } (*board)[pos[index].x][pos[index].y] . } } }该函数是整个算法的引擎逻辑分四层全局剪枝递归一开始就检查*succ一旦某条分支已经找到完整解立即终止后续所有分支的探索对应文档中找到一组解以后就不需要再继续回溯了直接返回即可的优化。递归出口index len(pos)表示所有空白格都已成功填完此时将*succ置为true标志着找到完整解。枚举候选数字for i : 1; i 10; i依次尝试数字1到9先经过checkSudoku三路校验通过且尚未找到解!*succ时才把数字写入棋盘byte(i) 0把整数转换为对应的 ASCII 字符。落子与回退写入后递归进入下一个空白格index1若递归返回后发现已找到解直接返回不再尝试否则说明当前数字导致死路回退——把该格重新写成.继续尝试下一个数字。这里的回退backtrack正是回溯算法区别于普通 DFS 的核心棋盘状态在递归返回后必须恢复到尝试前的样子保证兄弟分支的校验不受污染。3.4 校验函数 checkSudoku行、列、宫三路检查func checkSudoku(board *[][]byte, pos position, val int) bool { // 判断横行是否有重复数字 for i : 0; i len((*board)[0]); i { if (*board)[pos.x][i] ! . int((*board)[pos.x][i]-0) val { return false } } // 判断竖行是否有重复数字 for i : 0; i len((*board)); i { if (*board)[i][pos.y] ! . int((*board)[i][pos.y]-0) val { return false } } // 判断九宫格是否有重复数字 posx, posy : pos.x-pos.x%3, pos.y-pos.y%3 for i : posx; i posx3; i { for j : posy; j posy3; j { if (*board)[i][j] ! . int((*board)[i][j]-0) val { return false } } } return true }checkSudoku在(pos.x, pos.y)处尝试放入val前必须确认三处均无冲突任意一处重复即返回false行检查固定行号pos.x遍历整行 9 列跳过.若存在等于val的数字则冲突列检查固定列号pos.y遍历整列 9 行规则同上宫检查这是最巧妙的一步。通过pos.x - pos.x%3与pos.y - pos.y%3将当前坐标对齐到所在 3x3 宫的左上角再以双重循环遍历该宫 3x3 共 9 个单元格逐一比对。取模运算让任意坐标都能快速映射到其所属九宫格是本题的关键几何技巧。只有三路检查全部通过val才被允许写入棋盘。该函数在 核心源码 中有明确的注释标注三段检查的职责。四、测试用例与运行验证仓库为本题提供了完整的单测位于 37. Sudoku Solver_test.go包含两方面验证4.1 LeetCode 官方示例用例测试构造了 LeetCode 官方给出的数独谜题para37.s调用solveSudoku原地求解后与标准答案ans37.s对比para37{[][]byte{ {5, 3, ., ., 7, ., ., ., .}, {6, ., ., 1, 9, 5, ., ., .}, {., 9, 8, ., ., ., ., 6, .}, {8, ., ., ., 6, ., ., ., 3}, {4, ., ., 8, ., 3, ., ., 1}, {7, ., ., ., 2, ., ., ., 6}, {., 6, ., ., ., ., 2, 8, .}, {., ., ., 4, 1, 9, ., ., 5}, {., ., ., ., 8, ., ., 7, 9}}}求解结果应为{5, 3, 4, 6, 7, 8, 9, 1, 2}, {6, 7, 2, 1, 9, 5, 3, 4, 8}, {1, 9, 8, 3, 4, 2, 5, 6, 7}, {8, 5, 9, 7, 6, 1, 4, 2, 3}, {4, 2, 6, 8, 5, 3, 7, 9, 1}, {7, 1, 3, 9, 2, 4, 8, 5, 6}, {9, 6, 1, 5, 3, 7, 2, 8, 4}, {2, 8, 7, 4, 1, 9, 6, 3, 5}, {3, 4, 5, 2, 8, 6, 1, 7, 9}}4.2 分支覆盖测试测试文件还专门覆盖了putSudoku中*succ已为true时的提前返回分支见测试文件第 62-71 行的注释与代码构造一个already : true的初始标志调用putSudoku后断言already保持为true从而验证全局剪枝逻辑没有副作用。4.3 运行测试本仓库采用gotest.sh脚本统一执行全量测试并生成覆盖率报告见 gotest.shgo test -covermodeatomic -coverprofilecoverage.txt ./leetcode/...也可以只针对本题目录运行go test -v ./leetcode/0037.Sudoku-Solver/项目模块声明为github.com/halfrost/LeetCode-Go见 go.mod测试代码与题解代码同属leetcode包直接复用仓库内的structures等辅助模块即可编译运行。五、复杂度分析从源码结构推断从代码实现可以推断出如下复杂度特征时间方面最坏情况下需要对每个空白格尝试 9 个数字每次尝试都要进行行、列、宫共 27 次比较理论最坏复杂度为指数级O(9^m)m为空白格数量但由于唯一解 找到即返回的剪枝实际求解速度远快于最坏情形LeetCode 官方案例几乎瞬间完成。空间方面递归深度等于空白格数量m最多 81辅助切片pos也最多容纳 81 个坐标因此空间复杂度为O(m)其中m为空格数。可优化方向基于本实现的扩展思考可以引入每行/每列/每宫候选数字位图bitmask把校验从线性扫描降为常数时间也可以采用 MRVMinimum Remaining Values优先填充候选数最少的格子启发式进一步加速——但就本题数据规模而言当前的简洁实现已经足够。六、小结通过本题可以完整掌握回溯算法的标准四步法约束定义行/列/宫不重复→ 状态收集空白格列表→ 递归尝试1-9 枚举 三路校验→ 失败回退恢复.。仓库实现用三个短小精悍的函数完成了从入口收集、递归求解到合法性校验的全部逻辑配合官方用例与分支覆盖测试是一份可直接运行、可直接复用的数独求解器参考实现。相关文档与代码路径汇总如下题解文档英文版website/content.en/ChapterFour/0001~0099/0037.Sudoku-Solver.md题解文档中文版leetcode/0037.Sudoku-Solver/README.md核心实现37. Sudoku Solver.go单元测试37. Sudoku Solver_test.go【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/9 6:51:56

SK-005_从 0 到 1 读懂 SKILL.md:一个文件的完整 Anatomy

一、痛点引入:打开 SKILL.md 一脸懵 你下载了一个 Skill,打开 SKILL.md 一看: --- name: code-review description: 自动审查代码质量 version: 1.0.0 --- # Code Review Skill ...这些字段到底是什么意思?哪些是必填的&#xf…

2026/11/9 6:51:56

draw.io 桌面版:3 种安装方式实现完全离线绘图

draw.io 桌面版:3 种安装方式实现完全离线绘图 【免费下载链接】drawio-desktop Official electron build of draw.io 项目地址: https://gitcode.com/GitHub_Trending/dr/drawio-desktop draw.io 桌面版(drawio-desktop)是基于 Elect…

2026/11/9 6:48:42

泸州电工作业培训费用千万别踩坑,别交了钱考不过白费

泸州电工作业培训费用千万别踩坑,别交了钱考不过白费 怕考不过白交培训费?泸州电工作业培训费用千万别踩坑,选错了机构真的一分钱都捞不回。尤其是在特种作业这块,证书就是你的饭碗,考不过等于失业。现在市面上培训机构鱼龙混杂,价格参差不齐,很多人交…

2026/11/9 6:48:42

海盐县电工证复审全攻略:良心建议,别再被中介骗

海盐县电工证复审全攻略:良心建议,别再被中介骗 不知道去哪报名怕被中介坑?海盐县电工证复审流程复杂,很多人都在找靠谱渠道,结果一不小心就被坑了。今天我来给你一个 良心建议 ,教你如何安全、高效地完成海盐县电工证复审,别再走弯路。…

2026/11/9 6:48:42

电工证太忙没时间复习?外挂电工证有什么风险,网上查询全知道

电工证太忙没时间复习?外挂电工证有什么风险,网上查询全知道 工地太忙根本没时间复习考试,这事儿真不是个例,我身边不少工友都遇到过。为了赶工期、抢进度,很多电工证考试干脆靠“外挂”过,结果一查 网上查询 发现, 外挂电工证有什么风险…

2026/11/9 6:48:42

茂名哪里有办电工证的,上岗必备怎么考更稳妥

茂名哪里有办电工证的,上岗必备怎么考更稳妥 之前考的证在外省能不能转过来?这个问题我听得太多了,很多人拿着外地的电工证,想在茂名找工作却卡在了“本地化认证”这一关。其实, 上岗必备…

2026/11/9 6:48:42

个人可否办电工证?新手怎么报名不踩坑

个人可否办电工证?新手怎么报名不踩坑 你是不是刚从工地下来,手里拿着一沓图纸,心里却空荡荡的?因为你知道, 急需特种作业证才能上岗找工作 ,特别是电工证,这玩意儿在工地上可是“通行证”!可问题是, 个人可否办电工证 ? 怎么报名…

2026/11/9 0:37:55

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/9 0:03:09

建设厅的特种工有哪些含金量高?别交完钱考不过

建设厅的特种工有哪些含金量高?别交完钱考不过 怕考不过白交培训费?别急,先搞清楚建设厅的特种工有哪些含金量高的证,再决定是不是值得投入时间和金钱。 建设厅的特种工证是建筑行业里最基础、也最实用的证书之一,涉及多个作业类别,每种证的 含金量…

2026/11/9 0:03:09

荆门市电工证报名怎么考才靠谱 全国通用证别交冤枉钱

荆门市电工证报名怎么考才靠谱 全国通用证别交冤枉钱 怕考不过白交培训费?荆门市电工证报名前必须知道这些避坑指南。别看网上一堆培训机构广告,真要报个电工证,很多人被坑得一塌糊涂。特别是那些打着“包过”旗号的,最后不是考试不过,就是证不是全国通…

2026/11/9 0:03:09

高空电工作业过程通过率揭秘:怎么选靠谱机构不被坑

高空电工作业过程通过率揭秘:怎么选靠谱机构不被坑 不知道去哪报名怕被中介坑?你不是一个人。现在特种作业证报名渠道五花八门,从线下培训机构到线上代理,真假难辨。尤其是像高空电工作业这类高风险、高门槛的作业类型,证书含金量和考试通过率直接影响你…

2026/11/9 6:30:27

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/7 14:50:12

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑