leetcode刷题日记-滑铁卢了家人们(解数独)

问题描述

在这里插入图片描述

解题思路

看到这个题,给我的感觉是什么玩意啊!仔细读题之后,真的没想到解题思路。然后看了题解,用到了回溯算法,感觉这个回溯和N皇后的问题差不太多。然后就照着思路尝试理解了一遍,感觉这种题目前针对我来讲的话,确实算是困难的题目。看来还是要学学回溯算法。思路根据代码理解。整体思路如下。
在 dfs 方法中,pos 表示当前处理的位置。如果 pos 等于 spaces 的长度,说明所有空格都已经填充完毕,将 valid 标记为 True 并返回。

获取当前空格的坐标 (i, j),然后尝试填充数字。对于每个数字(0 到 8),检查该数字是否可以填充到当前位置。如果满足条件,则标记该数字已被使用,更新数独表格,并继续下一个空格的填充。

在递归填充下一个空格之前,需要将之前的标记复原,以便在不同的分支中尝试不同的数字。

如果 valid 已经为 True,则表示已找到解,直接返回。

初始化 line、column 和 block 三个二维数组,用于记录每行、每列和每个 3x3 的块中数字的使用情况。

将数独表格中已有的数字标记为已使用,并将空格的坐标保存到 spaces 列表中。

调用 dfs(0) 开始填充数独表格。
通过深度优先搜索的方式尝试填充数独表格,同时通过回溯的方式处理不合法的填充,直到找到合法的解或者遍历完所有可能的情况。

代码如下


class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        def dfs(pos: int):
            nonlocal valid
            if pos == len(spaces):
                valid = True
                return
            
            i, j = spaces[pos]
            for digit in range(9):
                if line[i][digit] == column[j][digit] == block[i // 3][j // 3][digit] == False:
                    line[i][digit] = column[j][digit] = block[i // 3][j // 3][digit] = True
                    board[i][j] = str(digit + 1)
                    dfs(pos + 1)
                    line[i][digit] = column[j][digit] = block[i // 3][j // 3][digit] = False
                if valid:
                    return
            
        line = [[False] * 9 for _ in range(9)]
        column = [[False] * 9 for _ in range(9)]
        block = [[[False] * 9 for _a in range(3)] for _b in range(3)]
        valid = False
        spaces = list()

        for i in range(9):
            for j in range(9):
                if board[i][j] == ".":
                    spaces.append((i, j))
                else:
                    digit = int(board[i][j]) - 1
                    line[i][digit] = column[j][digit] = block[i // 3][j // 3][digit] = True

        dfs(0)

  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值