求可用数字之后三个条件的交集解法
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: None Do not return anything, modify board in-place instead.
"""
row = [set(range(1,10)) for _ in range(9)] #用三个set分别记录行,列,块可用的数字
col = [set(range(1,10)) for _ in range(9)]
block = [set(range(1,10)) for _ in range(9)]
todo = []
for i in range(9):
for j in range(9):
if board[i][j] != ".": #如果已经填了
row[i].remove(int(board[i][j])) #这一行不能用了
col[j].remove(int(board[i][j])) #这一列不能用了
block[(i//3)*3+j//3].remove(int(board[i][j])) #这一块也不能用了
else: #记录要填的位置
todo.append((i,j))
def backtrack(n):
if n == len(todo): #全部填完
return True
i,j = todo[n] #从第一个要填的位置开始填
b = (i//3)*3+j//3
for val in row[i]&col[j]&block[b]: #这个位置所处的行,列,块剩余的可填数字。这里相当于把所有的都试一遍
row[i].remove(val)
col[j].remove(val)
block[b].remove(val)
board[i][j] = str(val) #填这个数
if backtrack(n+1): #如果n+1不行,那么回退重新试新的
return True
row[i].add(val)
col[j].add(val)
block[b].add(val)
return False #没填完,但是可以使用的数没了,说明前面填错了,回溯。
backtrack(0)
常规回溯解法
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: None Do not return anything, modify board in-place instead.
"""
def helper(board,r,c,k):
for i in range(9):
if board[r][i] == str(k):
return 0
for j in range(9):
if board[j][c] == str(k):
return 0
bi,bj = (r//3)*3,(c//3)*3
for ii in range(bi,bi+3):
for jj in range(bj,bj+3):
if board[ii][jj] == str(k):
return 0
return 1
def backtrack(board):
for i in range(9):
for j in range(9):
if board[i][j] == ".":
for k in range(1,10):
if helper(board,i,j,k) == 1:
board[i][j] = str(k)
if backtrack(board):
return True
board[i][j] = "."
return False
return True
backtrack(board)