题目:
编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。
思路:
回溯
解答:
方法一:回溯
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
def isValid(row,col,val,board):
n=len(board)
#判断列
for i in range(n):
if board[row][i]==str(val):
return False
#判断行
for i in range(n):
if board[i][col]==str(val):
return False
#判断小格子
row=(row//3)*3
col=(col//3)*3
for i in range(row,row+3):
for j in range(col,col+3):
if board[i][j]==str(val):
return False
return True
def tracebacking(board):
n=len(board)
for i in range(n):
for j in range(n):
if board[i][j]!='.':
continue
#填数
for k in range(1,10):
if isValid(i,j,k,board):
board[i][j]=str(k)
#找到即返回
if tracebacking(board):
return True
board[i][j]='.'
return False
return True
tracebacking(board)
方法二:原始解法
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
#按行进行遍历
def dfs(board,x,y):
if y==9:
return dfs(board,x+1,0)
if x==9:
return True
if board[x][y]!='.':
return dfs(board,x,y+1)
#为board[x][y]填值
for i in range(9):
if (not row[x][i]) and (not col[y][i]) and (not box[x//3][y//3][i]):
board[x][y]=str(i+1)
row[x][i],col[y][i],box[x//3][y//3][i]=1,1,1
if dfs(board,x,y+1):
break
#board[x][y]回退到初始状态,尝试下一个值
else:
board[x][y]='.'
row[x][i],col[y][i],box[x//3][y//3][i]=0,0,0
return board[x][y]!='.'
row=[[0]*9 for i in range(9)]
col=[[0]*9 for i in range(9)]
box=[[[0]*9 for _ in range(3)] for _ in range(3)]
for i in range(9):
for j in range(9):
if board[i][j]!='.':
t=int(board[i][j])-1
row[i][t],col[j][t],box[i//3][j//3][t]=1,1,1
dfs(board,0,0)