解数独
题目描述:
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
-
数字
1-9
在每一行只能出现一次。 -
数字
1-9
在每一列只能出现一次。 -
数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
空白格用 '.'
表示。
一个数独。
答案被标成红色。
Note:
- 给定的数独序列只包含数字
1-9
和字符'.'
。 - 你可以假设给定的数独只有唯一解。
- 给定数独永远是
9x9
形式的。
解题思路:
利用分步验证和递归的方式解答
-
本题主要利用了
solver()
函数进行填入数字的递归操作,利用isValue()
函数来判断填入的数字是否满足题意。因为我们只能在原有矩阵中进行修改,所以只能返回True
或者False
来判断当前所填入的数字是否满足要求 -
在函数
solver()
中,我们遍历每一个9x9
矩阵的点,将1-9
的数字依次填入,如果满足要求,就进行下一个位置的递归,如果不满足要求,就在该位置使用下一个数字进行递归(if self.isValue(board, i, j) and self.solver(board)
),如果所有数字都不满足要求,则可能是上一次选择的数字不满足要求,就倒退回去,重新选择,同时将数字转为.
(board[i][j] = '.'
) -
在函数
isValue()
中,需要判断每一行,每一列,以及在每一个3x3
小矩阵内是否满足要求,这里可以参考第36题解数独的方法
Python源码:
from typing import List
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
self.solver(board)
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
# 检查每个正方形是否符合
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 solver(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的时候调用递归
if self.isValue(board, i, j) and self.solver(board):
return True
# 到这个位置说明填入的数不太行,所以先空着
board[i][j] = '.'
# 进行完当前可选的所有数字都不行,说明上一次决策有问题,返回false
return False
return True
欢迎关注我的github:https://github.com/UESTCYangHR