📅  最后修改于: 2023-12-03 15:11:33.357000             🧑  作者: Mango
本次算法测验即将开始!本次测试的主题为 Sudo 放置。这是熟悉的游戏,我们将会测试你的算法设计和实现能力。本次测试总共有 5 个问题,每个问题都有不同的难度级别。答题时间为 40 分钟,祝你好运!
在一个 $n \times n$ 的矩阵中填充数独问题的数字,使得每一行、每一列和每一 个 $3 \times 3$ 的子矩阵中的数字都是 $1$ 到 $9$ 的数字,且不同的个数为 $9$。
编写一个程序,以二维数组表示的 Sudo 棋盘作为输入,输出一个已经填充好数字的 Sudo 棋盘。如果无法找到可行的解决方案,则返回一个空的 Sudo 棋盘。
注意:您可以假设矩阵的尺寸为 $n\times n$,其中$n$是一个平方数。
二维数组表示的 Sudo 棋盘,其中 $0$ 表示空格。
示例:
[
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,3,0,0,0,0,0,0,0],
[0,0,0,0,7,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,0]
]
输出一个已经填充好数字的 Sudo 棋盘,如果无法找到可行的解决方案,则返回一个空的 Sudo 棋盘。
示例:
[
[5,6,7,8,1,4,3,9,2],
[1,9,8,6,5,2,4,7,3],
[4,3,2,9,8,7,5,6,1],
[8,1,5,3,7,6,2,4,9],
[3,7,9,1,2,8,6,5,4],
[2,4,6,5,9,0,7,3,8],
[6,8,1,4,3,5,9,2,7],
[7,2,3,0,6,9,8,1,5],
[9,5,4,2,0,1,0,0,6]
]
本题可以采用 DFS 深度优先遍历 + 回溯搜索的方式求解。
首先我们需要对给定的矩阵进行预处理,找出所有尚未填充数字的位置。这样我们就可以依次对这些位置进行搜索。
对于每个未填充数字的位置,我们需要判断在这个位置上可以填充哪些数字。这里可以使用一个辅助函数来完成。
在搜索过程中,需要满足 Sudo 规则,即每一行、每一列和每一个 $3\times 3$ 的子矩阵中的数字都是 $1$ 到 $9$ 的数字,且不同的个数为 $9$。
def fillSudoku(board):
"""
:type board: List[List[int]]
:rtype: List[List[int]]
"""
n = len(board)
empty_cells = []
for i in range(n):
for j in range(n):
if board[i][j] == 0:
empty_cells.append((i, j))
def check_row(i, num):
for j in range(n):
if board[i][j] == num:
return False
return True
def check_col(j, num):
for i in range(n):
if board[i][j] == num:
return False
return True
def check_block(i, j, num):
bi, bj = i // 3 * 3, j // 3 * 3
for k in range(3):
for l in range(3):
if board[bi + k][bj + l] == num:
return False
return True
def backtrack(index):
if index == len(empty_cells):
return True
i, j = empty_cells[index]
for num in range(1, 10):
if (check_row(i, num)
and check_col(j, num)
and check_block(i, j, num)):
board[i][j] = num
if backtrack(index + 1):
return True
board[i][j] = 0
return False
backtrack(0)
return board
本题经典的搜索算法题目,需要对矩阵中各个未填充位置进行判断,判断此时可以填充哪些数字,再根据 Sudo 规则进行搜索剪枝。相对其他算法难度较小,是典型的算法考察题目之一。