Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'
.
You may assume that there will be only one unique solution.
A sudoku puzzle...
...and its solution numbers marked in red.
Subscribe to see which companies asked this question
class Solution(object):
def isValid(self, board,i,j):
row = [0]*10
col = [0]*10
mat = [0]*10
for jt in range(9):
if board[i][jt] != '.':
row[int(board[i][jt])] += 1
for temp in row:
if temp > 1:
return False
for it in range(9):
if board[it][j] != '.':
col[int(board[it][j])] += 1
for temp in col:
if temp > 1:
return False
m,n = i/3,j/3
for it in range(m*3,m*3+3):
for jt in range(n*3,n*3+3):
if board[it][jt] != '.':
mat[int(board[it][jt])] += 1
for temp in mat:
if temp > 1:
return False
return True
def findEmpty(self,board):
data = []
for i in range(9):
for j in range(9):
if board[i][j] == '.':
data.append((i,j))
return data
def findChoice(self,board,i,j):
row = []
col = []
mat = []
for jt in range(9):
if board[i][jt] != '.':
row.append(int(board[i][jt]))
for it in range(9):
if board[it][j] != '.':
col.append(int(board[it][j]))
m,n = i/3,j/3
for it in range(m*3,m*3+3):
for jt in range(n*3,n*3+3):
if board[it][jt] != '.':
mat.append(int(board[it][jt]))
return list(set(range(1,10)) - (set(row) | set(col) | set(mat)))
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
empty = self.findEmpty(board)
board_choice = []
result = [0]*len(empty)
for i in range(9):
for j in range(9):
if board[i][j] == '.':
board_choice.append(self.findChoice(board,i,j))
pt = 0
while pt < len(empty):
if result[pt] == 0:
result[pt] = board_choice[pt][0]
board[empty[pt][0]][empty[pt][1]] = str(result[pt])
else:
if board_choice[pt].index(result[pt]) == len(board_choice[pt]) - 1:
result[pt] = 0
board[empty[pt][0]][empty[pt][1]] = '.'
pt -= 1
continue
else:
result[pt] = board_choice[pt][board_choice[pt].index(result[pt]) + 1]
board[empty[pt][0]][empty[pt][1]] = str(result[pt])
if self.isValid(board,empty[pt][0],empty[pt][1]):
pt += 1
else:
continue
先介绍一下用到的几个工具函数:
def isValid(self, board,i,j):
这个函数用来判断在矩阵的i,j位置加入一个元素之后,矩阵是否满足数独条件。有个小技巧:只判断这一行/列/小方块的是否出现重复就可以。
def findEmpty(self,board):
用来找到矩阵中的空元素,返回他们的下标
def findChoice(self,board,i,j):
对于每一个元素提前计算可取的值的范围,缩小解的空间
主函数主要的思想是dfs,碰到不满足数独条件的分支就回溯到上一个节点。
class Solution(object):
#判断该数独是否合法
def isValid(self, board,i,j):
row = [0]*10
col = [0]*10
mat = [0]*10
for jt in range(9):
if board[i][jt] != -1:
row[board[i][jt]] += 1
for temp in row:
if temp > 1:
return False
for it in range(9):
if board[it][j] != -1:
col[board[it][j]] += 1
for temp in col:
if temp > 1:
return False
m,n = i/3,j/3
for it in range(m*3,m*3+3):
for jt in range(n*3,n*3+3):
if board[it][jt] != -1:
mat[board[it][jt]] += 1
for temp in mat:
if temp > 1:
return False
return True
#找到所有的空格子
def findEmpty(self,board):
return [(i,j) for i in range(9) for j in range(9) if board[i][j] == -1]
#找到一个空格子可能的取值范围
def findChoice(self,board,i,j):
row = [board[i][jt] for jt in range(9) if board[i][jt] != -1]
col = [board[it][j] for it in range(9) if board[it][j] != -1]
m,n = i/3,j/3
mat = [board[it][jt] for it in range(m*3,m*3+3) for jt in range(n*3,n*3+3) if board[it][jt] != -1]
return list(set(range(1,10)) - (set(row) | set(col) | set(mat)))
def solveSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: void Do not return anything, modify board in-place instead.
"""
#将board由str型转为int型
board_temp = []
for i in range(9):
board_temp.append([])
for j in range(9):
if board[i][j] == '.':
board_temp[i].append(-1)
else:
board_temp[i].append(int(board[i][j]))
empty = self.findEmpty(board_temp)
board_choice = []
result = [0]*len(empty)
for e in empty:
board_choice.append(self.findChoice(board_temp,e[0],e[1]))
#DFS算法
pt = 0
while pt < len(empty):
if result[pt] == 0:
result[pt] = board_choice[pt][0]
board_temp[empty[pt][0]][empty[pt][1]] = result[pt]
else:
if board_choice[pt].index(result[pt]) == len(board_choice[pt]) - 1:
result[pt] = 0
board_temp[empty[pt][0]][empty[pt][1]] = -1
pt -= 1
continue
else:
result[pt] = board_choice[pt][board_choice[pt].index(result[pt]) + 1]
board_temp[empty[pt][0]][empty[pt][1]] = result[pt]
if self.isValid(board_temp,empty[pt][0],empty[pt][1]):
pt += 1
else:
continue
#最后再转为str型
for i in range(9):
for j in range(9):
board[i][j] = str(board_temp[i][j])
做了一点小改动,加快了运行时间