方法:backtracking
这种方法是一种考虑到约束条件的回溯法,条件就是当检查每一个数字时,需要考虑每行,每列和所在的单元已经满足条件,这种问题又叫做满足约束条件问题,backtracking是最好理解的,就是按照每行每列组个元素检验,并填入新的满足条件的元素,一旦到达某一不,不满足时,用backtracking返回上一步,再带入新的元素检查,这种算法一般不用求时间复杂度,因为是NP 问题。
更好的方法有前馈和arc consistency 和 domain spliting,但目前不会应用。
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
# set csp
rows = [set() for i in range(9)]
cols = [set() for j in range(9)]
boxes = [set() for k in range(9)]
# init all constraint
for i in range(9):
for j in range(9):
if board[i][j] != ".":
num = int(board[i][j])
rows[i].add(num)
cols[j].add(num)
box_id = i // 3 * 3 + j // 3 # get box id:0-8
boxes[box_id].add(num)
# backtracking
def backTrack(i, j):
nonlocal solved # this should not be changed
if i == 9:
solved = True
return
next_i = i + (j + 1) // 9 # next (i, j)
next_j = (j + 1) % 9 # next (i, j)
if board[i][j] != ".":
backTrack(next_i, next_j)
else:
for num in range(1, 10):
box_id = i // 3 * 3 + j // 3
if num not in rows[i] and num not in cols[j] and num not in boxes[box_id]:
rows[i].add(num)
cols[j].add(num)
boxes[box_id].add(num)
board[i][j] = str(num)
backTrack(next_i, next_j)
# if not solved the problem at certain pos
if not solved:
rows[i].remove(num)
cols[j].remove(num)
boxes[box_id].remove(num)
board[i][j] = "."
solved = False # global var
backTrack(0, 0)