力扣做题37-解数独

编写一个程序,通过填充空格来解决数独问题。

一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。

一个数独。

答案被标成红色。

提示:

  • 给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
  • 你可以假设给定的数独只有唯一解。
  • 给定数独永远是 9x9 形式的。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sudoku-solver

解题思路

十字交叉双向循环链表是一种特殊的数据结构,专门用来解决精确覆盖的问题,相关资料可自行百度。
对于任何复杂的数独,任何语言均可在100ms内解出。
比如下面这个数独,官方目前给出的三个方法用python解时都需要几秒甚至几十秒。
[“080000600”,
“000400009”,
“070000805”,
“400000000”,
“030060090”,
“000720100”,
“093200064”,
“810300000”,
“000005000”]

下面给出用DLX解数独的详细代码(python版),解决困难的数独只需要60ms。

代码

class DLX:
    """
    十字交叉双向循环链表
    """

    def __init__(self, n):
        """
        :param n: 数独的阶数
        """
        self.n = n
        self.m = n ** 2 * n ** 2 * 4 + 1  # 总共的列数(标注节点数+头节点)
        self.max_nums = n ** 2 * n ** 2 * n ** 2 * 4 + self.m  # 最大节点编号

        # 用下标表示节点编号,下标0表示节点0(即头节点),下标1表示节点1,以此类推...
        self.u = [0 for _ in range(self.max_nums)]  # 记录节点的上链接点
        self.d = [0 for _ in range(self.max_nums)]  # 记录节点的下链接点
        self.l = [0 for _ in range(self.max_nums)]  # 记录节点的左链接点
        self.r = [0 for _ in range(self.max_nums)]  # 记录节点的右链接点
        self.row = [0 for _ in range(self.max_nums)]  # 记录节点所在的行
        self.col = [0 for _ in range(self.max_nums)]  # 记录节点所在的列

        # 设置首行的上下左右链接关系
        for i in range(self.m):
            self.u[i] = i
            self.d[i] = i
            self.r[i] = i + 1
            self.l[i] = i - 1
            self.row[i] = 0
            self.col[i] = i
        self.head = 0
        self.l[self
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值