Leetcode题解
题目链接: 37. 解数独
难度: 困难
解题思路: 一道很明显的搜索题,用DFS来求解。但是需要对数据进行预处理。记录一下某个为被覆盖的点的行、列、3*3方块内的所有备选值。可以很有效的减少搜索次数。逻辑很简单,详见代码。
题解:
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
SIZE = 9
# 预处理,找到所有的行 列 方块的备选值
row_candidate = []
col_candidate = []
cube_candidate = []
visit_number = 0 # 表示未被填的空的数量
position = [] # 未被填空的位置
# 行
for i in range(SIZE):
candidate = [str(itera + 1) for itera in range(SIZE) ]
for j in range(SIZE):
if board[i][j] != '.':
candidate.remove(board[i][j])
row_candidate.append(candidate)
# 列
for i in range(SIZE):
candidate = [str(itera + 1) for itera in range(SIZE) ]
for j in range(SIZE):
if board[j][i] != '.':
candidate.remove(board[j][i])
col_candidate.append(candidate)
# 方块
for i in range(SIZE):
candidate = [str(itera + 1) for itera in range(SIZE) ]
for j in range(SIZE):
true_i = (i // 3) * 3 + j // 3
true_j = (i % 3) * 3 + j % 3
if board[true_i][true_j] != '.':
candidate.remove(board[true_i][true_j])
else:
visit_number += 1
position.append([true_i, true_j])
cube_candidate.append(candidate)
# 结束标志
self.res = False
# dfs
def dfs(i, roc = row_candidate, coc = col_candidate, cuc = cube_candidate):
visit = []
if visit_number == i:
print("board = ", board)
self.res = True
# board = tboard # 最后的结果
return
# 三种备选值的位置
roc_index = position[i][0]
coc_index = position[i][1]
cuc_index = (position[i][0]//3 ) * 3 + position[i][1] // 3
# 去掉相同的值
temp_set = set(roc[roc_index]) & set(coc[coc_index]) & set(cuc[cuc_index])
# print(temp_set)
for ts in temp_set:
if self.res:
return
if ts in visit:
continue
# 标记
visit.append(ts)
board[position[i][0]][position[i][1]] = ts
roc[roc_index].remove(ts)
coc[coc_index].remove(ts)
cuc[cuc_index].remove(ts)
dfs(i + 1, roc, coc, cuc)
# 还原标记
visit.remove(ts)
roc[roc_index].append(ts)
coc[coc_index].append(ts)
cuc[cuc_index].append(ts)
# dfs遍历每个未被覆盖的点
dfs(0)