力扣-37-递归与回溯 python解题思路
本文代码使用回溯,用于记录个人编写回溯的思路
代码思路看注释即可
力扣37
题目:力扣37解数独
相关题目:力扣36有效的数独,两题相关,可先看链接中的文章
# 注意:调用class中的函数或者数组都是使用self.的格式调用
# 提醒自己,别丢冒号
class Solution:
# 设置数组,用于记录数独数字使用情况
# 详细可见力扣36的思路
def __init__(self):
self.row = [[0] * 9 for _ in range(9)]
self.col = [[0] * 9 for _ in range(9)]
self.block = [[0] * 9 for _ in range(9)]
# 回溯函数,简单粗暴地命名为huisu
def huisu(self, i, j, board):
# i的范围是0-8,为 9时说明已经为数独找到解
if i == 9:
return True
# j的范围同样是0-8,为 9就切换到下一行
if j == 9:
return self.huisu(i + 1, 0, board)
# 先找到非空的数独格子
if board[i][j] != ".":
return self.huisu(i, j + 1, board)
# b可以根据i,j求出,不用传递,节省开销
b = (i // 3) * 3 + (j // 3)
# 数独中只能填入1-9的值,遍历0-8,包含8,填入数独时加1即可
for s in range(9):
# 该数字不可用
# 可能是与同一行或者同一列或者同一格产生冲突
if self.row[i][s] or self.col[j][s] or self.block[b][s]:
continue
else:
self.row[i][s] = self.col[j][s] = self.block[b][s] = 1
board[i][j] = str(s + 1)
# 当前格子已经找到适合的数组
# 递归点:下一个格子是否返回True依赖于下一个的下一个格子
# 递归到最后是直到成功为最后一个格子找到合适的数字中间所有huisu return 1
if self.huisu(i, j + 1, board):
return True
# 回溯点:下一个格子没有找到合适的数字
# 还原borad和self中的辅助数组
else:
board[i][j] = '.'
self.row[i][s] = self.col[j][s] = self.block[b][s] = 0
return False
def solveSudoku(self, board: List[List[str]]) -> None:
"""
Do not return anything, modify board in-place instead.
"""
for i in range(9):
for j in range(9):
if board[i][j] == ".":
continue
b = (i // 3) * 3 + (j // 3)
num = int(board[i][j]) - 1
self.row[i][num] = self.col[j][num] = self.block[b][num] = 1
self.huisu(0, 0, board)
return board
递归与回溯
写递归与回溯时需要想到起点和终点,当前题目中的起点是第一个格子,终点是最后一个格子
然后需要考虑回溯点和递归点,在我个人的理解中就是失败与成功
当前题目中:
- 回溯点是无法找到合适的数字,需要还原环境
- 递归点是能找到合适的数字,需要进入下一步
根据回溯点和递归点,得到一个结构:
if 当前节点成功:
if 下一节点成功:
return True
# 下一节点失败
else:
还原环境,撤销当前节点的设置
那如何确保当前节点的设置不会重复执行呢?
# 思路为单向遍历, 不可回头
for item in range(9):
if item符合当前节点要求:
当前节点成功
# 当前节点成功后的结果要么是 return True 结束当前节点
# 要么是还原环境,所以直接continue 而不是 else continue
continue

1020

被折叠的 条评论
为什么被折叠?



