LeetCode-37、解数独-困难
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。
一个数独
答案被标成红色
Note:
- 给定的数独序列只包含数字
1-9
和字符'.'
。 - 你可以假设给定的数独只有唯一解。
- 给定数独永远是
9x9
形式的。
代码:
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
row = [set(range(1, 10)) for _ in range(9)] # 行剩余可用数字
col = [set(range(1, 10)) for _ in range(9)] # 列剩余可用数字
block = [set(range(1, 10)) for _ in range(9)] # 块剩余可用数字
empty = [] # 收集需填数位置
for i in range(9):
for j in range(9):
if board[i][j] != '.': # 更新可用数字
val = int(board[i][j])
row[i].remove(val)
col[j].remove(val)
block[(i//3)*3 + j//3].remove(val)
else:
empty.append((i, j))
def backtrack(iter=0):
if iter == len(empty): # 填满empty
return True
i, j = empty[iter]
b = (i//3)*3 + j//3
for val in row[i] & col[j] & block[b]:
row[i].remove(val)
col[j].remove(val)
block[b].remove(val)
board[i][j] = str(val)
if backtrack(iter+1):
return True
row[i].add(val) # 回溯
col[j].add(val)
block[b].add(val)
return False
backtrack()