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

  • 题目描述
  • 解题思路
  • 代码详解
  • 注意点

题目描述

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

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

  • 数字 1-9 在每一行只能出现一次。
  • 数字 1-9 在每一列只能出现一次。
  • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

  1. 示例:

    输入: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”]]
    输出:[[“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”]]

解释:输入的数独如上图所示,唯一有效的解决方案如下所示:

提示:
board.length = 9
board[i].length = 9
board[i][j] 是一位数字或者 ‘.’
题目数据保证输入数独仅有一个解

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sudoku-solver
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

首先题目保证了只有一个解。方法:使用递归+回溯

先对原数组进行一次遍历,获取原数组的一些信息:
数独就是行、列、块不能有重复数字,那就设置row、col、sqr三个9×9的二维数组,[i][j]的内容代表第 i 行/列/块的数字 j+1 是否在之前出现过,如果出现置true

然后从左上角开始,对第一个为’.'的元素进行递归

递归中若遇到数字,则直接递归至下一个方块。若遇到’.'则以row、col、sqr三个数组为依据,从1~9逐个试探放入,也递归至下一个方块。若后续发现无法放入数字,则返回至上一个方块并将board回溯。

递归结束后,board被填满,直接返回即可

表述能力有限,不懂可直接看代码(别看长度长,很多都是括号占据的)

代码详解

class Solution {// 以row[i][j]为例说明:row[i][j]为true说明第i行的数字j+1出现在原数组中boolean[][] row = new boolean[9][9];boolean[][] col = new boolean[9][9];boolean[][] sqr = new boolean[9][9];public void solveSudoku(char[][] board) {// 这两层for获取原数组信息,将row、col、sqr初始化完毕for(int i = 0; i < 9; ++i) {for(int j = 0; j < 9; ++j) {if(board[i][j] != '.') {int num = board[i][j] - '0';row[i][num-1] = true;col[j][num-1] = true;sqr[i/3*3+j/3][num-1] = true;}}}// 这两个for是寻找第一个为'.'的方格,找到就递归本方块,递归完毕直接跳出循环即可for(int i = 0; i < 9; ++i) {for(int j = 0; j < 9; ++j) {if(board[i][j] == '.') {func(i, j, board);break;}}}}public boolean func(int i, int j, char[][] board) {int nexti = 0; // 下一个方块的iint nextj = 0; // 下一个方块的jif(i == -1 && j == -1) {return true; // 说明已递归完毕}if(i != 8 && j == 8) { // 列递归至末位,转到下一行的开头nexti = i + 1;nextj = 0;} else if(j != 8) { // 从左往右、从上到下遍历nexti = i;nextj = j + 1;} else if(i == 8 && j == 8) { // 最后一个方块了,置-1标记一下而已nexti = -1;nextj = -1;}if(board[i][j] != '.') {return func(nexti, nextj, board); // 是数字就递归至下一个方块} else {for(int n = 1; n <= 9; ++n) { // 不是数字的话就将1~9试探性放入,并以row、col、sqr为依据if(row[i][n-1] || col[j][n-1] || sqr[i/3*3+j/3][n-1]) {continue; // 当前数字已出现过,试探下一个数字} else {// 若当前数字未出现过,试探性放入board[i][j] = (char)('0' + n);row[i][n-1] = true;col[j][n-1] = true;sqr[i/3*3+j/3][n-1] = true;if(!func(nexti, nextj, board)) { // 递归不顺就还原/回溯board[i][j] = '.';row[i][n-1] = false;col[j][n-1] = false;sqr[i/3*3+j/3][n-1] = false;} else {return true; // 递归顺利就返回true}}}return false; // 若运行至此说明1~9都无法放入,说明前面有数字放错了,需要回溯至前一个方块,前一个方块的数字会继续试探下去}}
}

注意点

  • 不要忘记回溯(就像是用铅笔填数独时,填错了要擦除一样)

【LeetCode】第37题——解数独(难度:困难)相关推荐

  1. LeetCode—37. 解数独(困难)

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

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

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

  3. Leetcode每日一题:37.sudoku-solver(解数独)

    得用到DFS,一条路走到黑: 做这道题得时候一直在想 如何在line / 9 == 1的时候直接返回呢 开始准备用goto 后来改变主意设一个flag就行了 bool flag = false; bo ...

  4. [LeetCode]高频算法题

    建议在准备面试前的1-2周过一遍,这里尽量用简短的几个词,记录每道题的核心解法,帮助记忆 怎么用这个文档: 1)如果你还有1-2个月开始面试,那就跟着这个文档一道一道的写吧,看看里面说的解法是否符合你 ...

  5. LeetCode高频题37. 解数独

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

  6. 代码随想录刷题|LeetCode 332.重新安排行程 51. N皇后 37. 解数独

    目录 332.重新安排行程 思路 重新安排行程 51. N皇后 思路 N皇后 37. 解数独 思路 解数独         这三道题目都是困难题目,都是根据代码随想录的思路总结书写,慢慢理解,慢慢熟练 ...

  7. Leetcode困难笔记 37.解数独

    解数独,回溯法即可.从左到右,从上到下,检查每种数字是否可以放进格子,如果可以就放入,一直搜索直到解数独完成. class Solution{public:bool finish = false;bo ...

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

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

  9. LintCode 802. 数独(回溯)/ LeetCode 37. 解数独

    1. 题目 编写一个程序,通过填充空单元来解决数独难题. 空单元由数字0表示. 你可以认为只有一个唯一的解决方案. LeetCode 37 题类似,把 int 改成 char,注意转换 2. 解题 行 ...

最新文章

  1. OpenLayers辅助函数Util.js(三)
  2. LIVE 预告 | 旷视王剑锋:丢弃Transformer,FCN也可以实现端到端检测
  3. 独家 | 一文读懂如何用深度学习实现网络安全
  4. SAP Forecasting and Replenishment for Retail – A short Overview【中英文双语版】
  5. 经验共享:由备份和负载均衡
  6. MOS2010的界面介绍和定制方法简介【资料汇集】
  7. MySQL的行转列、列转行、连接字符串 concat、concat_ws、group_concat函数用法
  8. ssm(Spring+Spring mvc+mybatis)Dao层配置sql的文件——DeptDaoMapper.xml
  9. 第十五节:Asp.Net Core MVC和WebApi路由规则的总结和对比-第二十节
  10. MySQL 体系结构
  11. 交际过程的两个基本环节_要客品味 | 人际交往礼仪——交际礼仪的基本原则
  12. 最火开源框架MVVMHabit的简单集成使用
  13. Hive中运行任务报错:Error during job, obtaining debugging information...
  14. ​分享几个威胁情报平台
  15. 方舟编译器的构建(笔记)
  16. 仁微电子-医院智慧病房物联网系统
  17. JAVA开发与运维(配置中心Apollo的使用)
  18. Metasploit(MSF)渗透测试框架使用教程及基本命令
  19. 安装vfp9遇到的问题
  20. iframe 高度100%时,出现垂直滚动条

热门文章

  1. 修改默认文件夹的图标(使用注册表)
  2. EDI/B2B相关工作到底做什么?Webmethods又是什么?
  3. 采集迅雷地址php,迅雷thunder://地址与普通url地址转换php
  4. 交房不验等于毁房!详细总结验房16项 别等开发商跑了才醒悟!
  5. 90. 基于Notes/Domino的文档工作流系统(二)
  6. mandriva 2010 安装手记
  7. python飞机大战概要设计_飞机大战游戏开发文档(Android版)
  8. 中国梦·雷锋美-关爱困境青少年学生公益活动
  9. 回调地狱终结者——Promise
  10. 行楷基础-一篇文章带你练出完美行楷