🧠 Python小练习系列 Vol.5:数独求解(经典回溯 + 剪枝)
🧩 数独不仅是益智游戏,更是回溯算法的典范!本期我们将用 DFS + 剪枝 的方式一步步求解一个标准 9x9 数独。
🧩 一、题目描述
给定一个部分填充的 9×9 数独棋盘,请编写一个程序将其填完,使每行、每列、每个 3×3 宫内的数字 1~9 均不重复。
示例输入:
python
board = [
["5","3",".",".","7",".",".",".","."],
["6",".",".","1","9","5",".",".","."],
[".","9","8",".",".",".",".","6","."],
["8",".",".",".","6",".",".",".","3"],
["4",".",".","8",".","3",".",".","1"],
["7",".",".",".","2",".",".",".","6"],
[".","6",".",".",".",".","2","8","."],
[".",".",".","4","1","9",".",".","5"],
[".",".",".",".","8",".",".","7","9"]
]
🧠 二、解题思路
使用回溯 + 剪枝,依次尝试将数字 1~9 填入空格中,若不符合数独规则则回退重试。
核心逻辑:
- 递归寻找空白格,尝试填入合法数字
- 若数字在当前行、列或 3x3 宫格中已出现,则剪枝
- 全部填满时即为解
👨💻 三、Python代码实现
python
def solve_sudoku(board):
def is_valid(r, c, ch):
for i in range(9):
if board[r][i] == ch or board[i][c] == ch:
return False
box_r, box_c = 3 * (r // 3) + i // 3, 3 * (c // 3) + i % 3
if board[box_r][box_c] == ch:
return False
return True
def dfs():
for i in range(9):
for j in range(9):
if board[i][j] == ".":
for ch in map(str, range(1, 10)):
if is_valid(i, j, ch):
board[i][j] = ch
if dfs():
return True
board[i][j] = "."
return False
return True
dfs()
📌 四、输出示例(运行后 board 被原地修改)
python
solve_sudoku(board)
for row in board:
print(" ".join(row))
🧩 五、关键点总结
步骤 | 说明 |
---|---|
查找空位 | 使用双层循环寻找 . |
合法判断 | 检查当前行、列、宫格是否冲突 |
回溯回退 | 无法填充时,重置该位置为 . |
✅ 本题是典型的「排列填空 + 剪枝」模型
💡 六、进阶挑战
- 🧠 输出所有可能解(需去掉第一个 return)
- ⚡ 加速优化:用位运算预处理可选值
- 🎨 制作 GUI 数独求解器(Tkinter/PyQt)
❤️ 结语
数独是一道优雅的全排列题目,透过回溯 + 剪枝,掌握"选择-尝试-回退"的算法核心!
📌 下一期预告:单词搜索(网格回溯)
👉 点个赞 👍 + 收藏 🌟,学透回溯,从数独开始!