【leetcode】解数独
文章目录
- topic
- 思路
- 1. 判断数独是否有效
- 2. 解数独
- 代码
topic
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
- 数字 1-9 在每一行只能出现一次。
- 数字 1-9 在每一列只能出现一次。
- 数字 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】解数独相关推荐
- Leetcode 解数独
解数独 题目描述: 编写一个程序,通过填充空格来解决数独问题.一个数独的解法需遵循如下规则:数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实线分 ...
- LeetCode——解数独
题目: 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实线分隔的 ...
- Java实现 LeetCode 37 解数独
37. 解数独 编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实 ...
- Leetcode算法Java全解答--37. 解数独
Leetcode算法Java全解答–37. 解数独 文章目录 Leetcode算法Java全解答--37. 解数独 题目 想法 结果 总结 代码 我的答案 大佬们的答案 测试用例 其他 题目 编写一个 ...
- 【无聊刷题】leetCode之解数独
题意:解数独,空缺的方格用.表示. 解法:就是典型的回溯法,用row[i][j],column[i][j],grid[i][j]表示i行,i列,i格j是否用.用flag表示当前是否有解.若有解,则不用 ...
- Leetcode 37:解数独(超详细的解法!!!)
编写一个程序,通过已填充的空格来解决数独问题. 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一个以粗实线分隔的 3x3 ...
- 【LeetCode】第37题——解数独(难度:困难)
[LeetCode]第37题--解数独(难度:困难) 题目描述 解题思路 代码详解 注意点 题目描述 编写一个程序,通过填充空格来解决数独问题. 数独的解法需 遵循如下规则: 数字 1-9 在每一行只 ...
- LeetCode高频题37. 解数独
LeetCode高频题37. 解数独 提示:本题是系列LeetCode的150道高频题,你未来遇到的互联网大厂的笔试和面试考题,基本都是从这上面改编而来的题目 互联网大厂们在公司养了一大批ACM竞赛的 ...
- LeetCode算法题11:递归和回溯-解数独
文章目录 解数独 回溯 : 仅仅在实现方式上有区别 总结 解数独 题目链接:https://leetcode-cn.com/problems/sudoku-solver/ 题目描述:编写一个程序,通过 ...
- LeetCode 36有效的数独37解数独(八皇后问题)
公众号:bigsai 回复进群加入打卡 有效的数独 判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列 ...
最新文章
- 微软10亿美元砸入OpenAI:明为AGI,暗争谷歌,被指云计算换投资
- ORACLE——重做日志文件管理
- 基于CAD/CAM的三维控件
- 卸载idea2020删除以前的配置_推荐一款只有5M大小的绿色良心的卸载工具!
- Oracle11g安装完成后给用户解锁
- 1000人系统服务器配置,win云服务器在线1000人配置
- Django访问静态资源
- 三菱FX PLC编程口通讯协议详解
- 集合的概念以及集合框架的介绍
- windows7内部版本7601副本不是正版的解决方案
- 树莓派如何刷RetroPie,制作一个复古游戏机
- 互联网30年,总有人正年轻
- 百度鹰眼服务平台部署教程
- 关于服务器租用的利弊
- 运用HTML+CSS做CSDN博客首页
- 钣金cad插件_ug,CAD,SolidWorks,钣金??????非标等设计讲解
- 在word里按空格键文字不能向后移动
- matlab工具箱计算最小生成树_matlab_bgl 图论基本函数库, 相当丰富.包含工具箱、 、Dijkstra最短路径、 254万源代码下载- www.pudn.com...
- Rpc及Dubbo的概述
- 基于ADS1298的肌电图仪
热门文章
- 无线通信中存在的远近效应、多普勒效应、多径效应以及其应对策略
- Espresso指南一(Espresso下载、安装、设置、基础、速查表)
- 捣鼓PlantUML(三、时序图)
- 光环PgMP学友 | 4A成绩考过,学以致用才是“高分”!
- 解决Chrome插件安装时程序包无效:CRX_HEADER_INVALID
- 汉语拼音文件搜索项目
- 微信小程序css之盒子(box)模型
- linux抓bpdu包,用Python发送手工构建的BPDU(生成树协议包)
- Real-Time Rendering Chapter 1~6 读书笔记
- 计算机协会游园活动方案,计算机爱好者协会建设策划方案