37. 解数独
说实话,一开始看到这个题目的时候我是很拒绝的,因为感觉不确定性太大,然后去听了会歌,放松了一下心情,写下了第一版代码
维护3个数组+1个队列,数组分别存每行、每列、每单元格的数字情况
队列用于存储未填充的空白格
遍历数独,如果是空白,则加入visit队列,如果是数字,则在对应的三个数组中更新相应的信息。
在第一次中,我看通过率很高(事实证明是假的 )就直接用最简单的判断,如果该空白只有一个可以填的数字,那么填入这个数字并更新数组,因此超出时间限制了。
在第二版代码里用了枚举+回溯,
当递归到最后一个空白格后,如果仍然没有冲突,说明我们找到了答案;在递归的过程中,如果当前的空白格不能填下任何一个数字,那么就进行回溯。
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
rows = [[False]*9 for _ in range(9)] #行
lines = [[False]*9 for _ in range(9)]#列
cells = [[False]*9 for _ in range(9)]#格
visit = []
for i in range(9):
for j in range(9):
if board[i][j] == '.':
visit.append((i,j))
else:
rows[i][int(board[i][j])-1] = True
lines[j][int(board[i][j])-1] = True
cells[j//3+3*(i//3)][int(board[i][j])-1] = True
valid = False
def dfs(pos):
nonlocal valid
if pos == len(visit):
valid = True
return
x_,y_ = visit[pos]
for i in range(9):
if(rows[x_][i]==lines[y_][i]==cells[y_//3+3*(x_//3)][i]==False):
rows[x_][i]=lines[y_][i]=cells[y_//3+3*(x_//3)][i] = True
board[x_][y_] = str(i+1)
dfs(pos+1)
rows[x_][i]=lines[y_][i]=cells[y_//3+3*(x_//3)][i] = False
if valid:
return
dfs(0)
时间复杂度取决于给定的数组,复杂度上界为O(9^81)
甚至去挑战了一下高级+
枚举回溯永远滴神!