文章目录

  • topic
  • 思路
    • 1. 判断数独是否有效
    • 2. 解数独
  • 代码

topic

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

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

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

空白格用 ‘.’ 表示。


一个数独。

答案被标成红色。

Note:

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

思路

给定一个9x9数组board,先判断此数独是否有效或有解,若无解则打印“This is an invalid sudoku!”,若有解则打印“This is a valid sudoku!”,并解此数独打印结果。

1. 判断数独是否有效

定义一个函数,判断此数独是否有解:isValidSudoku(),输入参数是9x9的二维数组,返回值是True或False。函数体中依次判断此数独是否满足数独的三条解法规则。

第一条,数字 1-9 在每一行只能出现一次:依次取出board中每行数据i,用列表生成式去除列表i中所有的‘.’得到列表r,再将列表i变成集合去重,去除元素‘.’,得到i中所有非‘.’的元素集合row,若r与row长度相同说明该行中数字元素不重复,否则说明i中有重复的数字元素,一旦出现重复数字,此数独无效,直接返回False。

    for i in board:r=[j for j in i if j!='.']row=set(i)-{'.'}if len(r)!=len(row):return False

第二条,数字 1-9 在每一列只能出现一次:先遍历列表board,用列表生成式取出每列数据的列表temp,与第一条一样,除去temp中‘.’得到列表col,对列表temp去重,再删去元素‘.’得到集合c,比较集合c和列表col的长度,若长度相同说明该列数据无重复数字元素,若长度不同则违反了条件二,直接返回False。

    for i in range(9):temp=[board[j][i] for j in range(9)]col=[j for j in temp if j!='.']c=set(temp)-{'.'}if len(c)!=len(col):#print('col false:',i)return False

第三条,数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次:首先要取出每个3x3宫内的数据,采用列表切片取出三行每行三列的数据(首行首列位置由range(0,9,3)给出),每宫的数据存为列表temp,然后同前两条规则一样,去除‘.’的列表unit和去重的集合u比较长度,判断是否有重复数字。

    for i in range(0,9,3):for j in range(0,9,3):temp = board[i][j:j + 3] + board[i + 1][j:j + 3] + board[i + 2][j:j + 3]unit = [i for i in temp if i!='.']u=set(temp)-{'.'}if len(unit)!=len(u):return Falsereturn True

数独中所有行、列及3x3宫内数据全部满足以上三条规则,则判定此数独有效,返回True。

2. 解数独

定义解数独的函数solveSudoku(board),输入参数是待解的数独二维数组board,解数独的思路如下:

①首先找到数独中的第一个‘.’:如果找不到‘.’,说明已解完此数独,返回结果board即可(递归的基例);如果能找到,记下第一个‘.’的行列坐标(row,col),此位置为本次解的目标位置。

def solveSudoku(board):#①find position of the first '.'row,col=find_empty(board)if row==None:return board

定义一个函数,寻找第一个‘.’:find_empty()。输入参数为待解数独二维数组board,返回值为寻找到的第一个‘.’的行列索引(索引值0~8);当board中不存在‘.’时,返回两个None,代码如下:

def find_empty(board):for r in range(9):for c in range(9):if board[r][c]=='.':return r,celse:return None,None

②然后根据三条规则依次算出目标位置(row,col)的可行解集合key1、key2、key3,对这三个可行解集合求交集得到本轮可行解集合key。

    #②find feasible key for the positionkey1={'1','2','3','4','5','6','7','8','9'}-set(board[row])key2={'1','2','3','4','5','6','7','8','9'}-set([board[i][col] for i in range(9)])key3=find_key3(board,row,col)key=key1&key2&key3

③最后进行递归操作:
若key为空,说明此情况无解,直接返回False;
若key中有值,弹出一个填入目标位置,对填入一个可行解后的新数独进行下一轮的解,若下一轮解数独有返回值,则此返回值即为此数独的最终解,直接返回该结果即可;若下一轮解数独返回False,说明本次填入的解不对,继续从key中pop出其他可行解进行递归,直至得到最终结果。

    #③recursionwhile key:k = key.pop()board[row][col]=ktemp=solveSudoku(board)if temp:return tempelse:board[row][col] = '.'else:return False

代码

def find_key3(board,row,col):r=row//3*3c=col//3*3temp=board[r][c:c+3]+board[r+1][c:c+3]+board[r+2][c:c+3]key3={'1','2','3','4','5','6','7','8','9'}-set(temp)return key3
def find_empty(board):for r in range(9):for c in range(9):if board[r][c]=='.':return True,r,celse:return False,board,None
def solveSudoku(board):""":type board: List[List[str]]:rtype: void Do not return anything, modify board in-place instead."""#①find position of the first '.'row,col=find_empty(board)if row==None:return board#②find feasible key for the positionkey1={'1','2','3','4','5','6','7','8','9'}-set(board[row])key2={'1','2','3','4','5','6','7','8','9'}-set([board[i][col] for i in range(9)])key3=find_key3(board,row,col)key=key1&key2&key3#③recursionwhile key:k = key.pop()board[row][col]=ktemp=solveSudoku(board)if temp:return tempelse:board[row][col] = '.'else:return False
def isValidSudoku(board):""":type board: List[List[str]]:rtype: bool"""for i in board:r=[j for j in i if j!='.']row=set(i)-{'.'}if len(r)!=len(row):return Falsefor i in range(9):temp=[board[j][i] for j in range(9)]col=[j for j in temp if j!='.']c=set(temp)-{'.'}if len(c)!=len(col):return Falsefor i in range(0,9,3):for j in range(0,9,3):temp = board[i][j:j + 3] + board[i + 1][j:j + 3] + board[i + 2][j:j + 3]unit = [i for i in temp if i!='.']u=set(temp)-{'.'}if len(unit)!=len(u):return Falsereturn Truedef main():board=[["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"]]for i in board:print(i)if isValidSudoku(board):print('This is a valid sudoku! \nThe sudoku solution is as follow:\n')key = solveSudoku(board)for i in key:print(i)else:print('This is an invalid sudoku!')

【leetcode】解数独相关推荐

  1. Leetcode 解数独

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

  2. LeetCode——解数独

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

  3. Java实现 LeetCode 37 解数独

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

  4. Leetcode算法Java全解答--37. 解数独

    Leetcode算法Java全解答–37. 解数独 文章目录 Leetcode算法Java全解答--37. 解数独 题目 想法 结果 总结 代码 我的答案 大佬们的答案 测试用例 其他 题目 编写一个 ...

  5. 【无聊刷题】leetCode之解数独

    题意:解数独,空缺的方格用.表示. 解法:就是典型的回溯法,用row[i][j],column[i][j],grid[i][j]表示i行,i列,i格j是否用.用flag表示当前是否有解.若有解,则不用 ...

  6. Leetcode 37:解数独(超详细的解法!!!)

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

  7. 【LeetCode】第37题——解数独(难度:困难)

    [LeetCode]第37题--解数独(难度:困难) 题目描述 解题思路 代码详解 注意点 题目描述 编写一个程序,通过填充空格来解决数独问题. 数独的解法需 遵循如下规则: 数字 1-9 在每一行只 ...

  8. LeetCode高频题37. 解数独

    LeetCode高频题37. 解数独 提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目 互联网大厂们在公司养了一大批ACM竞赛的 ...

  9. LeetCode算法题11:递归和回溯-解数独

    文章目录 解数独 回溯 : 仅仅在实现方式上有区别 总结 解数独 题目链接:https://leetcode-cn.com/problems/sudoku-solver/ 题目描述:编写一个程序,通过 ...

  10. LeetCode 36有效的数独37解数独(八皇后问题)

    公众号:bigsai 回复进群加入打卡 有效的数独 判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列 ...

最新文章

  1. 微软10亿美元砸入OpenAI:明为AGI,暗争谷歌,被指云计算换投资
  2. ORACLE——重做日志文件管理
  3. 基于CAD/CAM的三维控件
  4. 卸载idea2020删除以前的配置_推荐一款只有5M大小的绿色良心的卸载工具!
  5. Oracle11g安装完成后给用户解锁
  6. 1000人系统服务器配置,win云服务器在线1000人配置
  7. Django访问静态资源
  8. 三菱FX PLC编程口通讯协议详解
  9. 集合的概念以及集合框架的介绍
  10. windows7内部版本7601副本不是正版的解决方案
  11. 树莓派如何刷RetroPie,制作一个复古游戏机
  12. 互联网30年,总有人正年轻
  13. 百度鹰眼服务平台部署教程
  14. 关于服务器租用的利弊
  15. 运用HTML+CSS做CSDN博客首页
  16. 钣金cad插件_ug,CAD,SolidWorks,钣金??????非标等设计讲解
  17. 在word里按空格键文字不能向后移动
  18. matlab工具箱计算最小生成树_matlab_bgl 图论基本函数库, 相当丰富.包含工具箱、 、Dijkstra最短路径、 254万源代码下载- www.pudn.com...
  19. Rpc及Dubbo的概述
  20. 基于ADS1298的肌电图仪

热门文章

  1. 无线通信中存在的远近效应、多普勒效应、多径效应以及其应对策略
  2. Espresso指南一(Espresso下载、安装、设置、基础、速查表)
  3. 捣鼓PlantUML(三、时序图)
  4. 光环PgMP学友 | 4A成绩考过,学以致用才是“高分”!
  5. 解决Chrome插件安装时程序包无效:CRX_HEADER_INVALID
  6. 汉语拼音文件搜索项目
  7. 微信小程序css之盒子(box)模型
  8. linux抓bpdu包,用Python发送手工构建的BPDU(生成树协议包)
  9. Real-Time Rendering Chapter 1~6 读书笔记
  10. 计算机协会游园活动方案,计算机爱好者协会建设策划方案