现在的我,遇到困难的题也波澜不惊了 ㄟ( ▔, ▔ )ㄏ
本文答案参考自LeetCode官方题解。
题目描述
编写一个程序,通过填充空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。
数独啊 (* ̄︿ ̄)
我们玩数独的时候肯定是先填一个,检验一下,然后再填下一个。
照着这个思想,我们就容易想出 回溯 算法。
【方法1】回溯(加递归)
检验条件是:每行、每列、每个宫格都不能有数字重复,
所以对 第 i 行,第 j 列,我们填了 某个数字 number
可以这样:
row[ i ][ number ] = True
column[ j ][ number ] = True
block[ i/3][ j/3 ][ number ] = True
来表示 第 i 行,第 j 列,第 [i/3 , j/3] 个宫格已经有这个数字 number 了。
下面就可以回溯了:
- 先遍历整个数独,对每个已经有数字的位置按照上述方法 把 row、column、block 的某个位置设为 True
- 数出数独中还有多少个空位
- 遍历每个空位,尝试填入 1~9,
- 如果按照上述检验条件判断可以填入后,则填入数字,并把 row、column、block 的对应位置设为 True,递归地重复第3步,在递归的下一个语句把 row、column、block 的对应位置设为 False(这是回溯的关键)
- 当所有空位都填完后就可以返回答案啦[耶]
【优化1】二进制数组压缩
方法1 中使用了二维和三维的数组,
那么有什么优化方法可以把吓人的二维三维数组“变小”一点吗?[思考]
那就使用 二进制数组压缩 吧(这名字是我自己取的[捂脸])
上图:
从右往左看,可以表示某一行(列、宫格)中已经有数字 1、3、7 。
这样就能节省空间了。
当然,在更改时要使用 位运算。
【优化3】枚举优化
LeetCode官方题解里还有一个优化叫 “枚举优化”,
但是我没弄懂[捂脸][捂脸][捂脸]