算法_回溯_解数独

article/2025/10/2 1:27:22

文章目录

  • 解数独
    • 1.解法
    • 2.总结
      • python
      • 算法

解数独

leetcode链接

1.解法

这道题是一个棋盘问题,而棋盘问题是一个典型的回溯问题。

首先思考普通人(这里指没有受过专业训练的人)解数独的方法,那就是首先在空白位置假设一个数字,然后在这个假设的基础上去填别的数,如果发现到最后无法填满,则证明假设不成立,然后换一个数继续假设。

上面的思想非常符合回溯的思想,画成图如下所示:
在这里插入图片描述
所以我们现在可以进行回溯三部曲:

  1. 确定函数头

    首先思考函数的参数,因为一般的回溯都是通过每次修改参数(比如让参数+1等等),然后再进行操作,但这道题比较特殊,我们来看上图中取1的例子,我们确定取1的位置是通过从头(即row=0,col=0)遍历行和列的方式来确定在空白处取1,取完1后,再进行下一次操作时,发现我们还是要从头遍历行和列才能确定下一个空白的位置,因此这里的参数为空, 即不需要任何参数,因为每一次的操作都是从头开始,不需要在上一层递归的基础上确定某些参数。

    有些人可能会问:第二次找空白值的时候,不是可以从上一次递归的列(col)+1开始吗?这样我们的参数就可以加上col了。

    答:因为下一次找空白值的时候有可能是在下一列,也有可能在下一行,我们还要写一些if语句来进行逻辑判断,然后确定下一层递归时参数是row+1,还是col+1,因此不如每一次都从头开始遍历,这样代码会简洁一些,并且不会影响时间复杂度。

     def backtracking():
    
  2. 确定递归出口:

    递归出口是所有的空都被填完了的时候,那么什么时候就可以知道所有的空都填完了呢,即row==len(board)。

     if row == len(board):return
    

    但是这里有一个问题,就是函数头是没有row参数的,我们写这个出口会出问题,这里可以先看下面,下面会给出解释。

  3. 确定逻辑部分:

    逻辑部分就是每次从头遍历行和列,找到下一个空白的位置,然后从1到9逐次填入空白位置,然后进行下一层的递归,只要找到一个合法答案,就可以退出整个程序了(因为数独只有一个答案)

     for row in range(len(board)): # 遍历行for col in range(len(board[0])): # 遍历列if board[row][col]!='.': # 找到下一个空白位置continuefor i in range(1,10): # 给空白位置填上数字if isValid(row,col,str(i),board): # 如果该数字合法,即没有相同数字在同行,同列,同宫board[row][col] = str(i) # 填上if backtracking(): # 递归return True # 这里的return True是给一个信号,证明找到答案了board[row][col] = '.' # 回溯return False # 如果执行到这里了,证明[1,9]都没有return True(即该空白位置填[1,9]都不成立),那么就不存在答案了,就可以回溯了return True # 此时row==len(board),即填满了棋盘
    

    这里其实已经涵盖了上面的递归出口,即最后一行return True,因为如果能执行到最后一行,证明row和col都遍历完最后一个位置了,因此直接return True即可,就不用上面的判断了。

  4. 判断数字是否合法:

     def isValid(row,col,i,board):# 检查行for c in range(len(board[0])):if board[row][c]==i:return False# 检查列for r in range(len(board)):if board[r][col]==i:return False# 检查宫rstart = (row // 3) * 3cstart = (col // 3) * 3for r in range(rstart,rstart+3):for c in range(cstart,cstart+3):if board[r][c]==i:return Falsereturn True
    

    这里检查是否同列和同行很容易,只要用循环判断同行同列是否存在重复数字即可。难点在于如何判断同宫。

    给定一个位置[row][col],想判断同宫里面是否有相同数字需要如下步骤:

    1. 首先给定一个位置[row,col],需要它所在的宫
    2. 知道了它所在的宫,再找到该宫的比较有代表性的位置(比如第一位,最后一位,最中间一位,这里的代表性指的是确定了这个位置,那么该宫的其他位置也都能确定)

    首先画出图:
    在这里插入图片描述

    1.首先找到位置[row,col]和宫的联系:

    我们先从左到右,从上到下给每个宫按行和列编号(蓝色字体),发现如果每个位置的(row//3)就是对应的宫的行数,(col//3)就是对应的宫的列数。

    2.然后找到宫和有代表性位置的联系:

    发现如果宫按照行和列编号,那么行和列都*3,就变成了该宫的第一个元素的位置

    所以代码中写到,rstart = (row // 3) * 3,cstart = (col // 3) * 3,找到了第一个位置,我们只要遍历行和列后+3的范围内的元素中是否有相同元素即可。

整体代码:

def solveSudoku(board):def backtracking():for row in range(len(board)):for col in range(len(board[0])):if board[row][col]!='.':continuefor i in range(1,10):if isValid(row,col,str(i),board):board[row][col] = str(i)if backtracking():return Trueboard[row][col] = '.'return Falsereturn True # 此时row==len(board),即填满了棋盘def isValid(row,col,i,board):# 检查行for c in range(9):if board[row][c]==i:return False# 检查列for r in range(9):if board[r][col]==i:return False# 检查宫rstart = (row // 3) * 3cstart = (col // 3) * 3for r in range(rstart,rstart+3):for c in range(cstart,cstart+3):if board[r][c]==i:return Falsereturn Truebacktracking()

2.总结

python

string 转 int : i = int(s)
int 转 string : s = str(i)

算法

回溯算法中确定参数的方法:

找到递归时需要在上一层递归的基础上进行操作的参数。

例如:行,列等等

def backtracking(row)backtracking(row+1)

http://chatgpt.dhexx.cn/article/DZuiQQgY.shtml

相关文章

Java编程实战12:解数独

目录 解数独题目示例 1提示 解答解题思路完整代码 解数独 题目 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内…

使用java解数独

说明 先根据规则解数独, 规则1: 如果备选数字只有一个, 那么就填入这个数字规则2: 如果在3*3单元格中, 或者一行, 或者一列中, 某个备选数字在所有的备选数字中只出现了一次, 那么就填入这个数字. 再暴力破解数独, 依次填入备选数字, 如果不能解开, 换下一个备选数字, 直到数独…

力扣 37. 解数独

一、题目描述 编写一个程序,通过填充空格来解决数独问题。 数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。数独部分空格内已填入了数字&#xf…

LeetCode算法 —— 解数独

题目如下所示: 编写一个程序,通过已填充的空格来解决数独问题。 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 ‘.…

C语言——解数独程序[源码]

用C语言写的解数独的程序。在linux下测试成功运行。 效果如图&#xff1a; 这是带解的数独&#xff0c;需要填写的部分用数字0代替。 这是程序运行后的效果图。看看&#xff0c;数独已经搞定啦&#xff5e;&#xff5e;&#xff5e; 程序源码如下&#xff1a; #include <…

用 Python 解数独(Sudoku)

芬兰数学家因卡拉花费3个月时间设计出的世界上迄今难度最大的数独。数独是 9 横 9 竖共有 81 个格子&#xff0c;同时又分为 9 个九宫格。规则很简单&#xff1a;每个空格填入 1~9 任意一个数字&#xff0c;需要保证每个横排和竖排以及九宫格内无相同数字。 解数独是一个可有可…

解数独c++

解数独 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; 数…

MATLAB 解数独

数独是一种较为常见的游戏&#xff0c;一般有4乘4、6乘6、9乘9几种&#xff0c;就像下面这种&#xff0c;本文也是主要求解此类数独。 此外还有一些奇形怪状的&#xff0c;如下图两种&#xff0c;均是不规则的&#xff0c;在此并不会涉及&#xff0c;但会在以后发布代码以及过程…

Leetcode 解数独

解数独 题目描述&#xff1a; 编写一个程序&#xff0c;通过填充空格来解决数独问题。一个数独的解法需遵循如下规则&#xff1a;数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。提示&#xff1a;…

再战leetcode (解数独)

37. 解数独 题目描述 回溯法 leetcode题解 代码 public class Test {public static void main(String[] args) {char[][] board {{5, 3, ., ., 7, ., ., ., .},{6, ., ., 1, 9, 5, ., ., .},{., 9, 8, ., ., ., ., 6, .},{8, ., ., ., 6, ., ., ., 3},{4, ., ., 8, ., 3, .…

回溯算法解数独问题(java版)

下面来详细讲一下如何用回溯算法来解数独问题。 下图是一个数独题&#xff0c;也是号称世界上最难的数独。当然了&#xff0c;对于计算机程序来说&#xff0c;只要算法是对的&#xff0c;难不难就不知道了&#xff0c;反正计算机又不累。回溯算法基本上就是穷举&#xff0c;解这…

014. 解数独

1.题目链接&#xff1a; 37. 解数独 2.解题思路&#xff1a; 2.1.题目要求&#xff1a; 暂时的理解就是&#xff0c;编写一个程序然后自动填完数独&#xff0c;填完返回&#xff08;不用求解各种不同的数独组合&#xff09; 填的时候&#xff0c;数字要满足的规则&#xff1…

回溯算法—解数独

什么是回溯法&#xff1f; 回溯法&#xff08;探索与回溯法&#xff09;是一种选优搜索法&#xff0c;又称为试探法&#xff0c;按选优条件向前搜索&#xff0c;以达到目标。但当探索到某一步时&#xff0c;发现原先选择并不优或达不到目标&#xff0c;就退回一步重新选择&…

解数独--难的一批

1题目 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。&#xff08;请参考示例图&#xff09; 数…

解数独 — Python

文章目录 解数独1、程序简介示例&#xff1a;输入&#xff1a;输出&#xff1a;解释&#xff1a;提示&#xff1a; 2、程序代码3、运行结果 解数独 1、程序简介 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每…

【每日刷题】解数独

题目地址 https://leetcode-cn.com/problems/sudoku-solver/ 题目描述&#xff1a;解数独 编写一个程序&#xff0c;通过已填充的空格来解决数独问题。 一个数独的解法需遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-…

算法学习:37. 解数独

解数独 题目链接&#xff1a;力扣题目链接 难度&#xff1a;困难 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫…

数独解题方法大全

数独这个数字解谜游戏&#xff0c;完全不必要用到算术&#xff01;会用到的只是推理与逻辑。解题方法分两大类&#xff1a;直观法和候选数法。 直观法就是不需要任何辅助工具&#xff0c;从接到数独谜题的那一刻起就可以立即开始解题。绝不猜测。数独直观法解题技巧主要有&…

37.解数独

37. 解数独&#xff08;难度&#xff1a;困难&#xff09; 题目链接&#xff1a;https://leetcode-cn.com/problems/sudoku-solver/ 编写一个程序&#xff0c;通过已填充的空格来解决数独问题。 一个数独的解法需遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。数…

安装搜狗输入法成功,每次都折腾,记录一下这次的成功经验。

1&#xff1a;卸载fcitx sudo apt-get --purge fcitx* 2&#xff1a;清理系统内的无用的软件包 sudo apt-get --purge autoremove 3&#xff1a;到搜狗官网下载搜狗拼音输入法&#xff0c;选择你系统对应的软件包&#xff0c;我系统是64位的&#xff0c;所以我选择了amd64的 ht…