请你判断一个 9 x 9
的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。(请参考示例图)
注意:
- 一个有效的数独(部分已被填充)不一定是可解的。
- 只需要根据以上规则,验证已经填入的数字是否有效即可。
- 空白格用
'.'
表示。
示例 1:
输入:board = [["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"]] 输出:true
示例 2:
输入:board = [["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"]] 输出:false 解释:除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。 但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
提示:
board.length == 9
board[i].length == 9
board[i][j]
是一位数字(1-9
)或者'.'
步骤 1:题目分析与定义
问题定义:
给定一个 9×99 \times 99×9 的数独棋盘,验证棋盘上已填入的数字是否符合数独规则:
- 每行中数字
1-9
不能重复。 - 每列中数字
1-9
不能重复。 - 每个 3×33 \times 33×3 的小方格内数字
1-9
不能重复。
输入:
- 一个 9×99 \times 99×9 的二维数组
board
,其中每个元素为字符'1'
到'9'
或'.'
(代表空格)。
输出:
- 布尔值,
true
表示数独有效,false
表示无效。
限制与边界条件:
- 棋盘大小固定为 9×99 \times 99×9。
- 数组中仅包含
'1'
到'9'
或'.'
。 - 棋盘可能只部分填充。
步骤 2:解题思路与算法设计
这是一个约束检查问题,解决方案需要验证三个条件(行、列、小方格)是否满足数独规则。考虑到问题的性质,使用集合存储已经出现的数字是较为高效的选择,这可以确保检查重复的操作在 O(1)O(1)O(1) 时间内完成。
方案概述
- 检查行:对于每一行,用一个集合来记录该行中已出现的数字。如果数字重复出现,则判定数独无效。
- 检查列:对每一列进行类似的检查,使用一个集合记录已出现的数字。
- 检查 3×33 \times 33×3 小方格:每个小方格可用集合记录出现的数字。遍历每个小方格的所有格子,检测是否有重复的数字。
最佳算法设计
我们可以在一次遍历中完成所有检查,采用三个集合数组来分别跟踪行、列和小方格中的数字。如下:
- 定义三个集合数组
rows[9]
、cols[9]
和boxes[9]
,分别用于存储行、列和小方格内的数字。 - 遍历整个棋盘,对于每个非
'.'
的格子,检查并更新相应的集合:- 如果数字已存在于对应的行集合
rows[row]
、列集合cols[col]
或小方格集合boxes[box_index]
中,则返回false
。 - 否则,将数字添加到相应集合中。
- 如果数字已存在于对应的行集合
复杂度分析:
- 时间复杂度:O(81)=O(1)O(81) = O(1)O(81)=O(1),因为数独大小固定为 9×99 \times 99×9。
- 空间复杂度:O(81)=O(1)O(81) = O(1)O(81)=O(1),我们只需三个固定大小的集合数组。
算法代码框架
该算法是一种直接的遍历与检查法,能够高效地检查数独有效性。
步骤 3:C++ 代码实现
步骤 4:解题启发与优化
启发:
- 集合的应用:使用集合来检测重复性操作是非常高效的,尤其在需要频繁检查和插入的场景下,集合的查找时间复杂度为 O(1)O(1)O(1)。
- 空间优化:可以进一步优化空间,将集合换成整型数组记录出现次数,但集合的可读性和代码简洁度较高。
效率提升:该算法遍历一次数独即可完成检查,适用于固定大小的棋盘,满足时间和空间复杂度需求,适合直接应用于生产环境。
步骤 5:算法实际应用
应用场景: 该算法可以应用于任何需要有效性检查和数据完整性验证的场景。例如在多维数据存储中,确保数据在行、列、或区域内不重复的约束要求。
实际应用示例: 在 仓库库存管理系统 中,可能需要确保某些特定区域(例如仓储格)内不会重复存放同一批次的产品。类似数独规则,每个仓储格有行、列、区域约束。这种算法可以用来自动检测仓库分区设置的有效性,避免重复存储。
实现方法: 设计一个与仓库布局一致的二维数组,模拟数独的行、列和区域约束,利用集合记录每个存储区域中已存入的批次号,防止重复存放,提高仓储效率。