解决数独

题目描述

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

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

数字 1-9 在每一行只能出现一次。

数字 1-9 在每一列只能出现一次。

数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

空白格用 '.' 表示。

一个数独。

答案被标成红色。

Note:

给定的数独序列只包含数字 1-9 和字符 '.' 。

你可以假设给定的数独只有唯一解。

给定数独永远是 9x9 形式的。

输入格式:

[["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]]

输出格式:

[['5', '3', '4', '6', '7', '8', '9', '1', '2'], ['6', '7', '2', '1', '9', '5', '3', '4', '8'], ['1', '9', '8', '3', '4', '2', '5', '6', '7'], ['8', '5', '9', '7', '6', '1', '4', '2', '3'], ['4', '2', '6', '8', '5', '3', '7', '9', '1'], ['7', '1', '3', '9', '2', '4', '8', '5', '6'], ['9', '6', '1', '5', '3', '7', '2', '8', '4'], ['2', '8', '7', '4', '1', '9', '6', '3', '5'], ['3', '4', '5', '2', '8', '6', '1', '7', '9']]

难度分类

困难

算法分析

这道题的的思考是在9x9的格子里面找到未填充的数字,比如当找到第n个未填充数字的格子,此时尝试在里面填写1可以保证当前行不冲突,列不冲突,小方块不冲突,那么就在第n个格子里面填写1,然后查看第n+1个格子,如果第n+1个格子发现填写1-9都冲突,说明第n个格子填写1的情况下无法找到解,此时我们需要回到第n个格子,填写另外一个不冲突的数字。一直到能填充到第81个格子为止。

将上述解题思路转换为代码设计:

  1. 定义col_used存储对应列的值,col_used = [[[] for i in range(9)]]
  2. 定义row_used存储对应行的值row_used=[[] for i in range(9)]
  3. 定义box_used存储对应小方块的值box_used = [[[], [], []] for i in range(3)]
  4. 先遍历九宫格将已填充的数字记录进对应的行,列和小方块
  5. 通过定义i,j,遍历遍历九宫格,i代表行的index,j代表列的index,遍历九宫格
  6. 读取当前九宫格的值,当当前九宫格的值为“”.“”的时候进行以下操作:

a)     从1-9九个数字中选择一个数字(满足与当前行的数字不冲突,列的数字不冲突,小方块的数字不冲突)填入当前格子

b)     将这个填入的数字记录进对应的行,对应的列,对应的小方块

c)     判断在当前格子填写当前数字的基础上接下来的格子填充能否填满九宫格

d)     如果当前格子填写数字的基础上接下来的格子填充不能填满九宫格,则需要取消当前数字的填充即①取消已填充的数字,②将已填充的数字从对应的行取出,③将已填充的数字从对应的列取出,④将已填充的数字从对应的小方块取出。然后尝试填入其他数字

e)     通过True和False判断能否填写九宫格,仅当第81个格子填写完成(填写的过程中已经进行了条件校验)才返回True,否则返回False

7.如果当前格子已有数字直接查看下一个格子

要点:如果下层返回False,证明基于当前数字的填充没有解,重置九宫格,行,列,小方块状态,选取新的数字填充

代码示例

def solveSudoku(board):
# 记录某一列已使用的数字
row_used = [[] for i in range(9)]
# 记录某一行已使用的数字
col_used = [[] for i in range(9)]
# 记录某一个小方块已使用的数字
box_used = [[[], [], []] for i in range(3)]
# 首先记录九宫格中每行,每列,每一个小方块中已使用的数字,以用于填充数字的时候检查填充数字是否已被使用
for i in range(len(board)):
for j in range(len(board[i])):
if board[i][j] in "":
row_used[i].append(board[i][j])
col_used[j].append(board[i][j])
box_used[i // 3][j // 3].append(board[i][j])
def dfs(board, i=0, j=0):
# 从左到右一个一个格子的遍历九宫格,当某一行遍历结束遍历下一行的第一个格子
if j == 9:
i,j = i+1,0
if i == 9:
return True
# 当遍历到某一行为".",即需要填充数字的时候,此时需要从1-9九个数字中选择一个不冲突的数字填入当前格子
if board[i][j] ==".":
for num in (""):
# 填充格子的前提条件是行不冲突(每一行每一个数字仅出现一次),列不冲突(每一列每一个数字仅出现一次),小方块不冲突(每一小方块每一个数字仅出现一次)
if num not in row_used[i] and num not in col_used[j] and num not in box_used[i // 3][j // 3]:
# 填充格子的同时需要将当前数字计入对应的行,列,小方块,用于当其他格子填充的时候检查是否行,列,小方块冲突
row_used[i].append(num)
col_used[j].append(num)
box_used[i // 3][j // 3].append(num)
# 填充当前格子
board[i][j] = num
# 填充完成格子后此时检查基于当前格子已经填充了数字的基础上,填充下一个格子
if dfs(board,i,j+1):
return True
# 如果下一个格子填充失败,1-9九个数字都有冲突,证明当前格子填充当前数字不能找到有效的解,此时需要找到另外一个数字来填充当前格子,因此需要将当前格子恢复原始状态
# 恢复当前格子为未填充状态
row_used[i].pop()
col_used[j].pop()
box_used[i // 3][j // 3].pop()
board[i][j] = "."
return False
# 当遍历到某一格子为数字,直接查看下一个格子
else:
return dfs(board, i,j+1)
dfs(board)
board = [["","",".",".","",".",".",".","."],["",".",".","","","",".",".","."],[".","","",".",".",".",".","","."],["",".",".",".","",".",".",".",""],["",".",".","",".","",".",".",""],["",".",".",".","",".",".",".",""],[".","",".",".",".",".","","","."],[".",".",".","","","",".",".",""],[".",".",".",".","",".",".","",""]]
solveSudoku(board)
print(board)

考点分析

  1. 带返回值的回溯用法

20190924-LeetCode解数独题目分享的更多相关文章

  1. 20191030-带返回值的回溯算法Leetcode解数独

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

  2. leetcode 36 有效的数独 哈希表 unordered_set unordersd_map 保存状态 leetcode 37 解数独

    leetcode 36 感觉就是遍历. 保存好状态,就是各行各列还有各分区divide的情况 用数组做. 空间小时间大 class Solution { public: bool isValidSud ...

  3. Leetcode之回溯法专题-37. 解数独(Sudoku Solver)

    Leetcode之回溯法专题-37. 解数独(Sudoku Solver) 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次.数字 1 ...

  4. Java实现 LeetCode 37 解数独

    37. 解数独 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实 ...

  5. [leetcode]37. Sudoku Solver 解数独

    Write a program to solve a Sudoku puzzle by filling the empty cells. A sudoku solution must satisfy  ...

  6. [LeetCode] Sudoku Solver 解数独,递归,回溯

    Write a program to solve a Sudoku puzzle by filling the empty cells. Empty cells are indicated by th ...

  7. [leetcode] 37. 解数独(Java)(dfs,递归,回溯)

    37. 解数独 1A 这个题其实15分钟左右就敲出来并且对了...但是由于我输错了一个数..导致我白白debug一个多小时.. 没啥难度,练递归-dfs的好题 class Solution { pri ...

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

    本文始发于个人公众号:TechFlow,原创不易,求个关注 数独是一个老少咸宜的益智游戏,一直有很多拥趸.但是有没有想过,数独游戏是怎么创造出来的呢?当然我们可以每一关都人工设置,但是显然这工作量非常 ...

  9. 【原创】一个基于简单剪枝的DFS解数独程序

    问题来源:leetCode Sudoku Solver Write a program to solve aSudoku puzzle by filling the empty cells. Empt ...

随机推荐

  1. [WEB安全]IIS-PUT漏洞

    目录 0x00 IIS简介 0x01 Put漏洞造成原因 0x02 实验环境搭建 0x03 需要用到的工具 0x04 IIS-PUT漏洞演示实战 0x05 常见请求协议 0x06 漏洞修复建议 0x0 ...

  2. PyTorch Tutorials 3 Neural Networks

    %matplotlib inline Neural Networks 使用torch.nn包来构建神经网络. 上一讲已经讲过了autograd,nn包依赖autograd包来定义模型并求导. 一个nn ...

  3. Java设计模式: 单例模式

    1.需要传递参数: public class Singleton{ private volatile static Singleton instance = null; private int val ...

  4. 手把手教你MyEclipseUML建模(上)

    手把手教你MyEclipseUML建模(上) 转 https://blog.csdn.net/qq_37939251/article/details/83444359 1.用UML 1建模 MyEcl ...

  5. java说明文档制作

    A:对工具类加入文档注释 B:通过javadoc命令生成说明书 * @author(提取作者内容) * @version(提取版本内容) * javadoc -d 指定的文件目录 -author -v ...

  6. 【转载】 AutoML总结

    原文地址: https://jinxin0924.github.io/2017/12/21/AutoML%E6%80%BB%E7%BB%93/ Posted by JxKing on December ...

  7. myeclipse启动的过程中没提示就自动退出,闪退的有效解决方法

      今天遇到一个问题,已经打开myeclipse的电脑因为非正常关机后myeclipse打不开了,进度条进到十分之一就闪退,什么提示都没有的解决方案如下: 1.打开myeclipse工作空间(存放项目 ...

  8. SpringCloud学习成长之路 五 路由器网关

    在微服务架构中,需要几个基础的服务治理组件,包括服务注册与发现.服务消费.负载均衡.断路器.智能路由.配置管理等,由这几个基础组件相互协作,共同组建了一个简单的微服务系统.一个简答的微服务系统如下图: ...

  9. PAT 甲级 1036 Boys vs Girls (25 分)(简单题)

    1036 Boys vs Girls (25 分)   This time you are asked to tell the difference between the lowest grade ...

  10. 通过本地Agent监控Azure sql database

    背景: 虽然Azure sql database有DMVs可以查看DTU等使用情况,但记录有时间限制,不会一直保留.为了更好监控Azure_sql_database上各个库的DTU使用情况.数据库磁盘 ...