回溯法定向爆破 9*9 数独
解数独是利用回溯算法的最经典的案例,废话不多说,直接爆破。
回溯算法我总结下来可以分两步走:
1. 构建 isValid() 函数。也就是先创建一个,可以判断 能否将当前元素加入数组中作为待定 的函数。对应本题,就是构建一个函数,用来判断现在传入的数字,是否有效,是否符合“数独的三个条件”;
-
数字
1-9
在每一行只能出现一次。 -
数字
1-9
在每一列只能出现一次。 -
数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
2. 构建回溯函数。其实回溯函数就是一个代码模板:
- 遍历当前树层;
- 判断当前遍历的元素有效性,有效则填入数组;
- 回溯,将之前填入的元素弹出。
只要按照以上两步走,其实无论什么回溯题目,都可以迎刃而解。另外,如果可以使用 numpy 等科学计算包,运算速度可以进一步提升。
对应 leetcode 题目:37. 解数独
代码如下:
class Solution:
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
Rboard = len(board)
Cboard = len(board[0])
def isValid(row, col, val, board):
for i in range(9):
if board[row][i] == val or board[i][col] == val:
return False
startRow = row // 3 * 3
startCol = col // 3 * 3
for i in range(startRow, startRow + 3):
for j in range(startCol, startCol + 3):
if board[i][j] == val:
return False
return True
def backtracking(board):
for i in range(Rboard):
for j in range(Cboard):
if board[i][j] != '.':
continue
for k in range(1, 10):
if isValid(i, j, str(k), board):
board[i][j] = str(k)
if backtracking(board):
return True
board[i][j] = '.'
return False
return True
backtracking(board)