class Solution:
    def solveSudoku(self , board):
        if not board: return []
        
        n = len(board)  # 9
        row = [[0] * (n + 1) for _ in range(n)]
        col = [[0] * (n + 1) for _ in range(n)]
        blk = [[0] * (n + 1) for _ in range(n)]
        
        def init():
            """初始化 row, clo, blk 记录出现过的数字"""
            for i in range(n):
                for j in range(n):
                    # 确定块 id
                    k = 3 * (i // 3) + j // 3
                    if (x := board[i][j]) != '.':
                        x = int(x)
                        row[i][x] = col[j][x] = blk[k][x] = 1
        
        def dfs(i, j):
            # 顺利达到最后一行,说明每个位置都满足要求
            if i == n: return True
            
            # 确定下一个遍历位置
            nxt_i = i if j != (n - 1) else i + 1
            nxt_j = j + 1 if j != (n - 1) else 0
            
            # 如果当前位置不需要填,直接到下一个位置
            if board[i][j] != '.':
                return dfs(nxt_i, nxt_j)
            
            # 对当前位置遍历每个可用数字
            k = 3 * (i // 3) + j // 3  # 块 id
            for x in range(1, 10):
                # 不可用,跳过
                if row[i][x] or col[j][x] or blk[k][x]:
                    continue
                # 可用,DFS回溯
                row[i][x] = col[j][x] = blk[k][x] = 1
                board[i][j] = str(x)
                if dfs(nxt_i, nxt_j):
                    return True
                board[i][j] = '.'
                row[i][x] = col[j][x] = blk[k][x] = 0
            
            return False
        
        init()
        dfs(0, 0)
        return board