编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
空白格用 '.'
表示。
一个数独。
答案被标成红色。
Note:
- 给定的数独序列只包含数字
1-9
和字符'.'
。 - 你可以假设给定的数独只有唯一解。
- 给定数独永远是
9x9
形式的。
思路:通过暴力搜索,每次确定往一个位置填入数据,填完后继续往下一个位置用递归的方式填,直到所有递归函数返回true,结果才为true。整体分为主函数,递归函数,判断位置是否有效函数。整体思路与八皇后相似,通过在循环中递归的手段不断回溯尝试可能的值。具体表现为我们代码里的for k in '123456789', 这句for循环搭配我们在if里的递归起的效果是:我把目前这个位置填‘1’,电脑你负责帮我算我这里填‘1’能不能解,换言之,电脑你要尝试后面所有待填位置的所有解来告诉我这里填‘1’ok不ok。如果不行,好,那我换‘2’,同样,电脑你需要帮我算后面所有待填位置所有组合加上我在这个位置填的‘2’能不能构成一组解,也即我这里填‘2’到底解不解的了。
代码及超详细解释:
class Solution(object):
def isValue(self,board,x,y):
#检查填入的坐标是否与行中已有元素相等
#列符合
for i in range(9):
if i != x and board[i][y] == board[x][y]:
return False
#检查行是否符合
for j in range(9):
if j != y and board[x][j] == board[x][y]:
return False
#检查每个正方形是否符合
#以下代码教会了我们如何遍历3*3方块
m = 3*(x // 3);n = 3*(y // 3)
for i in range(3):
for j in range(3):
if (i + m != x or j + n != y) and board[i + m][j + n] == board[x][y]:
return False
return True
def dfs(self,board):
#遍历每一个坐标
for i in range(9):
for j in range(9):
#找board里的需要填入的位置
if board[i][j] == '.':
#从可选之间选一个
for k in '123456789':
board[i][j] = k
#在if的时候调用递归
#如果这个递归可以返回true并且当前填入的数字也没毛病
#则证明我们解完了数独
if self.isValue(board,i,j) and self.dfs(board):
return True
#到这个位置说明填入的数不太行,所以把它先空着。
board[i][j] = '.'
#进行完当前可选的所有数字都不行,说明上一次决策有问题,返回false
return False
#所有'.'都填满,并且没毛病,返回true
return True
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
self.dfs(board)
版权声明:本文为weixin_41958153原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。