我们可以考虑按照「行优先」的顺序依次枚举每一个空白格中填的数字,通过递归 + 回溯的方法枚举所有可能的填法。当递归到最后一个空白格后,如果仍然没有冲突,说明我们找到了答案;在递归的过程中,如果当前的空白格不能填下任何一个数字,那么就进行回溯。
由于每个数字在同一行、同一列、同一个九宫格中只会出现一次,因此我们可以使用 \textit{line}[i]line[i],\textit{column}[j]column[j],\textit{block}[x][y]block[x][y] 分别表示第 ii 行,第 jj 列,第 (x, y)(x,y) 个九宫格中填写数字的情况。在下面给出的三种方法中,我们将会介绍两种不同的表示填写数字情况的方法。
九宫格的范围为 0 \leq x \leq 20≤x≤2 以及 0 \leq y \leq 20≤y≤2。
具体地,第 ii 行第 jj 列的格子位于第 (\lfloor i/3 \rfloor, \lfloor j/3 \rfloor)(⌊i/3⌋,⌊j/3⌋) 个九宫格中,其中 \lfloor u \rfloor⌊u⌋ 表示对 uu 向下取整。
由于这些方法均以递归 + 回溯为基础,算法运行的时间(以及时间复杂度)很大程度取决于给定的输入数据,而我们很难找到一个非常精确的渐进紧界。因此这里只给出一个较为宽松的渐进复杂度上界 O(9^{9 \times 9})O(9
9×9
),即最多有 9 \times 99×9 个空白格,每个格子可以填 [1, 9][1,9] 中的任意整数。
递归
思路
最容易想到的方法是用一个数组记录每个数字是否出现。由于我们可以填写的数字范围为 [1, 9][1,9],而数组的下标从 00 开始,因此在存储时,我们使用一个长度为 99