这两种题目都是比较典型的回溯法,从思路上来说并没有特别复杂的地方,但写法比较繁琐,而且重复的地方很多,所以适合用子函数的方法来写。另外,解数独是二维回溯,所以判断终止条件时要格外注意一下。
解数独
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
def could_place(row,col,d):
return not (d in rows[row] or d in cols[col] or d in boxes[box_index(row,col)])
def place_number(row,col,d):
#print(row,col)
board[row][col] = str(d)
rows[row].add(d)
cols[col].add(d)
boxes[box_index(row,col)].add(d)
def remove_number(row,col,d):
board[row][col] = "."
rows[row].remove(d)
cols[col].remove(d)
boxes[box_index(row,col)].remove(d)
def place_next(row,col):
nonlocal flag
if row == n - 1 and col == n - 1:
flag = True
return
if col == n - 1: backtrack(row + 1,0)
else: backtrack(row,col + 1)
def backtrack(row = 0,col = 0):
if board[row][col] == ".":
for d in range(1,10):
if could_place(row,col,d):
place_number(row,col,d)
place_next(row,col)
if flag == True: return
else: remove_number(row,col,d)
else:
place_next(row,col)
n = 9
flag = False
rows,cols,boxes = [set() for _ in range(n)],[set() for _ in range(n)],[set() for _ in range(n)]
box_index = lambda row,col:row // 3 * 3 + col // 3
for i in range(n):
for j in range(n):
if board[i][j] != ".":
place_number(i,j,int(board[i][j]))
backtrack()
return board
n皇后
class Solution:
def solveNQueens(self, n: int) -> List[List[str]]:
if not n: return []
def could_place(row,col):
return not (cols[col] + hill[row + col] + diag[row - col])
def place_queen(row,col):
queens.append((row,col))
cols[col] = 1
hill[row + col] = 1
diag[row - col] = 1
def remove_queen(row,col):
queens.remove((row,col))
cols[col] = 0
hill[row + col] = 0
diag[row - col] = 0
def add_solution():
temp = []
for _,element in sorted(queens):
temp.append("." * element + 'Q' + "." * (n - 1 - element))
result.append(temp)
def backtrack(row = 0):
if row == n:
add_solution()
return
for col in range(n):
if could_place(row, col):
place_queen(row,col)
backtrack(row + 1)
remove_queen(row,col)
queens = []
result = []
cols,hill,diag = [0] * n,[0] * (2 * n - 1),[0] * (2 * n - 1)
backtrack()
return result