【LeetCode】36. 有效的数独
解题思路
要验证一个 9x9 数独的有效性,需要同时满足三个条件:
- 行内无重复:每行中数字 1-9 最多出现一次
- 列内无重复:每列中数字 1-9 最多出现一次
- 宫内无重复:每个 3x3 宫内数字 1-9 最多出现一次
通过一次遍历即可完成所有验证,使用三个辅助数据结构分别记录行、列、宫的数字出现情况,确保时间复杂度最优。
关键步骤
-
数据结构初始化:
- 创建行记录器
rows:二维布尔数组,rows[i][num]表示第 i 行数字 num 是否出现 - 创建列记录器
cols:二维布尔数组,cols[j][num]表示第 j 列数字 num 是否出现 - 创建宫记录器
boxes:二维布尔数组,boxes[k][num]表示第 k 个宫数字 num 是否出现
- 创建行记录器
-
宫索引计算:
- 使用公式
boxIndex = (i/3)*3 + j/3确定单元格所属宫 - 例如位置
(4,5):(4/3)=1 → 1 * 3=3,5/3=1→3+1=4(第 5 个宫)
- 使用公式
-
遍历验证:
- 遍历每个单元格,跳过空白格('.')
- 若数字在行、列或宫中已记录,返回无效
- 否则更新三个记录器
代码实现
示例测试
func main() { // 示例1(有效) board1 := [][]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'}, } fmt.Println("示例1:", isValidSudoku(board1)) // true // 示例2(无效:左上宫重复8) board2 := [][]byte{ {'8', '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'}, } fmt.Println("示例2:", isValidSudoku(board2)) // false }
复杂度分析
- 时间复杂度:O(1)
固定遍历 81 个单元格(9x9 大小恒定) - 空间复杂度:O(1)
使用固定空间:3 个 9x10 的布尔数组(总计 270 字节)
关键点总结
- 宫索引计算:
公式(i/3)*3 + j/3将二维坐标映射到 0-8 的宫编号 - 一次遍历三验证:
单次遍历同时检查行、列、宫,避免多次扫描 - 字符转换技巧:
byte('5') - '0' = 5快速将字符转为数字索引 - 部分填充验证:
仅检查已填数字,不要求数独可解 - 布尔数组优化:
使用布尔值而非计数器,节省空间且避免整数运算

浙公网安备 33010602011771号