LeetCode37 使用回溯算法实现解数独,详解剪枝优化

本文详细介绍了如何运用回溯算法解决LeetCode上的数独问题,探讨了深度优先搜索策略,并重点讲解了在解题过程中实施的剪枝优化技巧,以提高算法效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文始发于个人公众号:TechFlow,原创不易,求个关注


数独是一个老少咸宜的益智游戏,一直有很多拥趸。但是有没有想过,数独游戏是怎么创造出来的呢?当然我们可以每一关都人工设置,但是显然这工作量非常大,满足不了数独爱好者的需求。

所以常见的一种形式是,我们只会选择难度,不同的难度对应不同的留空的数量。最后由程序根据我们选择的难度替我们生成一个数独问题。但是熟悉数独的朋友都知道,并不是所有的数独都是可解的,如果设置的不好可能会出现数独无法解开的情况。所以程序在生成完数独之后,往往还需要进行可行性检验。

所以今天文章的内容就关于如何解开一个数独

题意

LeetCode当中关于数独的是36和37两题,其中36要求判断一个给出的数独问题是否合法。37题则是给出一个必定拥有一个解法的数独的解。36题只需要判断在同行同列以及同区域当中是否有重复的数组出现,没太多的意思,所以我们跳过,直接进入37题紧张刺激的解数独问题。

题意没什么好说的,就是解这样一个数独:

要求数独当中的每行每列以及每个黑边框加粗标记的3*3的区域当中1-9都只出现一次。这个就是日常数独的规则,我想大家应该都能看明白。

解完成之后,是这样的:

题目就介绍完了,下面进入正题,即试着去解开这个数独。

解法

之前在写题解的时候,经常写的一句话就是从最简单的暴力解法开始。然而之前也说过了,并不是所有的问题都有简单粗暴的暴力解法的。比如这题就不行。不行的原因也很简单,因为我们并不知道数独当中留了多少空,我们很难简单地用循环去遍历所有填空的方法。

并且对于所有需要填数字的空格而言,前面的选择的数字会影响后面的决策,所以从原理上我们也不能直接遍历,需要用一个模式将这些待决策的区域串联起来。前面选过的数字后面自动不选,如果之后选错了数字还可以撤销,回到之前的选择。如果看过之前关于回溯算法文章的同学从我的描述当中应该能get到,这描述的其实是回溯算法的使用场景。

如果对回溯算法有所遗忘或者是新关注的同学可以点击下方链接,回顾一下关于搜索和回溯算法的讲解。

LeetCode 31:递归、回溯、八皇后、全排列一篇文章全讲清楚

和八皇后的对比

如果你还记得八皇后问题,再来看这道题可能会有一些感觉。也许你会觉得这两题好像有一些共通的部分,如果你再仔细思考一下,你也许会发现其实这看似迥异的两个问题实则是在说同一件事情。

你看,在八皇后当中,我们需要考虑的是皇后的位置,经过我们的优化之后,我们把问题转化成了每一行放置一个皇后。我们需要选择,在当前行皇后应该放在那里。而在本题当中,空白的位置是固定的,我们要选择的不再是位置,而是空白当中需要填什么数字。你看,一个是选择放置的位置,一个是选择放置的数字,表面上来看不太相同,但实际上都是在做同样一件事情,就是选择。再仔细分析一下,又会发现皇后可以选择的位置是固定的,这题数独上可供选择的数字其实也是固定的。

这难道不是同一个问题吗?

既然是同一个问题,那当然可以使用同一种方法。在八皇后当中我们通过回溯法枚举了皇后放置的位置,通过回溯修改之前的选择来找答案。这题本质上是一样的,我们枚举空白位置放置的数字,如果之后遍历不成功,找不到解,说明之前的放置错了,我们需要回溯回去修改之前的选择。

我们再来看下回溯问题的代码模板:

def dfs(depth):
if depth >= 8:
return
for
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值