Valid Sudoku

原题链接Valid Sudoku

判断给定的数独盘是否有效,数独盘中可能有空位置。

简述一下数独的规则,参考连接Sudoku Puzzles - The Rules.

  1. 每一行,数字1-9只能出现一次
  2. 每一列,数字1-9只能出现一次
  3. 每个3 * 3方格中,数字1-9只能出现一次。这里3 * 3方格只包括9个,即图片中加粗黑线分开的9个方格

其实就是每个点只能存在1-9这九个数字中的一个,满足每一行,每一列,每个3 * 3方格不能出现重复的数字

判断一个数独盘是否有效,只需要判断是否满足上述三个规则即可。另外,如果给出的数独盘像图片那样有些地方没有填充数字,也没有关系。只需要判断有数字的部分就好,比如说第一行只有5, 3, 7,那么可以判断第一行没有出现重复的数字,是满足规则一的。


肯定需要全部遍历一遍,每遍历到一个位置,就判断它所在的行,所在的列,所在的3 * 3方格是否已经存在同样的数字了,如果存在,返回false,否则,将这个数字添加到行,列,3 * 3方格的记录中。
所以需要分别记录每一行,每一列,每一个3 * 3方格都有那些数字出现过,其实就是3个二维数组

  1. 记录每一行都出现了哪些数字,vector<vector<int>> rows(9, vector<int>(10, 0));
  2. 记录每一列都出现了哪些数字,vector<vector<int>> columns(9, vector<int>(10, 0));
  3. 记录每个3 * 3方格都出现了哪些数字,vector<vector<int>> boxes(9, vector<int>(10, 0));

对于3 * 3方格,这里用vector<vector<int>> boxes(9, vector<int>(10, 0));形式表示,意思是这个数独盘是由9个3 * 3方格,编号从0到8。对于某个位置(row, column)而言,它所在的3 * 3方格编号为row / 3 * 3 + column / 3

表示方法,假设当前位置为(i, j),数字为n

  1. rows[i][n]表示第i行出现数字n的个数,不是1就是0
  2. columns[j][n]表示第j列出现数字n的个数,不是1就是0
  3. boxes[i / 3 * 3 + j / 3][n]表示当前位置所在的方格出现数字n的个数,不是1就是0

代码如下

class Solution {
public:bool isValidSudoku(vector<vector<char>>& board) {vector<vector<int>> rows(9, vector<int>(10, 0));vector<vector<int>> columns(9, vector<int>(10, 0));vector<vector<int>> boxes(9, vector<int>(10, 0));for(int i = 0; i < board.size(); ++i){for(int j = 0; j < board[i].size(); ++j){if(board[i][j] == '.')continue;int n = board[i][j] - '0';/* 如果之前有出现过(不为0),就说明数独盘无效 */if(rows[i][n] || columns[j][n] || boxes[i / 3 * 3 + j / 3][n])return false;/* 否则,更新每一行,每一列,所在方格的内容 */elserows[i][n] = columns[j][n] = boxes[i / 3 * 3 + j / 3][n] = 1;}}return true;}};

扩展

Sudoku Solver

原题链接Sudoku Solver

给定一个有效的数独盘,解出结果。
解一个数独盘就是要求把所有的空格都填上数字,要求仍然是满足上述三个规则,即

  1. 每一行,数字1-9只能出现一次
  2. 每一列,数字1-9只能出现一次
  3. 每个3 * 3方格中,数字1-9只能出现一次。这里3 * 3方格只包括9个,即图片中加粗黑线分开的9个方格

对于某个空格,它所能填充的数字需要满足

  1. 在所在行没有出现过的
  2. 在所在行没有出现过的
  3. 在所在3 * 3方格没有出现过的

所以在上面的问题中,已经把每一行,每一列,每个3 * 3方格出现的数字都找出了,接下来就是深度优先(dfs)把每个空格填上数字即可,当然填充的数字需要满足上面的要求。
如果填充到某个位置发现没有可选的数字了,就说明之前的某个位置选择错了,就回退到之前的位置,选择另一个满足上述要求的数字

代码如下

class Solution {
public:void solveSudoku(vector<vector<char>>& board) {vector<vector<int>> rows(9, vector<int>(10, 0));vector<vector<int>> columns(9, vector<int>(10, 0));vector<vector<int>> boxes(9, vector<int>(10, 0));/* 计算每一行,每一列,每个3 * 3方格中每个数字是否出现 */for(int i = 0; i < board.size(); ++i){for(int j = 0; j < board[i].size(); ++j){if(board[i][j] == '.')continue;int n = board[i][j] - '0';rows[i][n] = columns[j][n] = boxes[i / 3 * 3 + j / 3][n] = 1;}}bool done = false;dfs(board, rows, columns, boxes, 0, 0, done);   }private:void dfs(vector<vector<char>>& board, vector<vector<int>>& rows,vector<vector<int>>& columns, vector<vector<int>>& boxes,int row, int column, bool& done){/* 填充完成 */if(row >= board.size()){done = true;return;}/* 当前某一行的末尾,换到下一行 */else if(column >= board[row].size()){dfs(board, rows, columns, boxes, row + 1, 0, done);}/* 如果有数字,则不需要填充,继续下一个 */else if(board[row][column] != '.'){dfs(board, rows, columns, boxes, row, column + 1, done);}else{for(int n = 1; n <= 9; ++n){/* 如果数字出现过,就不能填充到当前位置 */if(rows[row][n] || columns[column][n] || boxes[row / 3 * 3 + column / 3][n])continue;/* 将填充的数字记录下来 */rows[row][n] = columns[column][n] = boxes[row / 3 * 3 + column / 3][n] = 1;board[row][column] = n + '0';/* 递归填充下一个空格 */dfs(board, rows, columns, boxes, row, column + 1, done);/* 如果完成,就退出 */if(done){return;}/* 否则,回到填充之前的状态,重新找数字 */else{rows[row][n] = columns[column][n] = boxes[row / 3 * 3 + column / 3][n] = 0;board[row][column] = '.';}}}}
};

每天一道LeetCode-----数独盘求解相关推荐

  1. leetcode17. 电话号码的字母组合--每天刷一道leetcode算法系列!

    作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...

  2. 数独游戏求解:解法适用于任意阶数的数独

    0.数独简介 数独(すうどく,Sūdoku)是一种运用纸.笔进行演算的逻辑游戏.以九阶数独为例,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字 ...

  3. leetcode最小面积_每日一道 LeetCode (51):盛最多水的容器

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  4. atoi函数_每日一道 LeetCode (50):字符串转换整数 (atoi)

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  5. 去掉数组最后一个元素_leetcode 34. 在排序数组中查找元素的第一个和最后一个位置每天刷一道leetcode算法系列!...

    作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...

  6. 二叉树层次遍历c语言_每日一道 LeetCode (23):二叉树的层次遍历 II

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  7. c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...

    ❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...

  8. 【python】一道LeetCode搞懂递归算法!#131分割回文串 #以及刷LeetCode的一点点小心得 [数据结构与算法基础]

    题目:给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串.返回 s 所有可能的分割方案. # 示例 输入: "aab" 输出: [["aa",&q ...

  9. 每日一道 LeetCode (16):求 x 的平方根

    每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...

最新文章

  1. 基于持久内存的 单机上亿(128B)QPS -- 持久化 k/v 存储引擎
  2. C#语言与面向对象技术(5)
  3. php之前代码,PHP语法检查源代码前控制
  4. linux比较10个文件是否一致,Linux中文件管理--cmp--比较两个文件是否有差异
  5. [USACO08MAR]土地征用Land Acquisition
  6. 计算机软件uml,[计算机软件及应用]UML.ppt
  7. FLASH闪存原理与实验
  8. SceneBuilder中文版
  9. html怎么取消打印空白页,怎么取消打印空白页:如何删除Excel工作表中的空白页...
  10. RxView学习及实现按钮防抖功能
  11. 【线性代数】上三角矩阵/下三角矩阵
  12. html页面中艺术字,html 生成艺术字
  13. QQ邮箱账号异常登录
  14. PS之基础知识汇总(总结版)
  15. 2018CSTC web2 writeup
  16. 机器翻译古文也翻车?读了20次“苟富贵勿相忘”后,谷歌:没钱的人总会被遗忘...
  17. Android PULL XML Praser
  18. mac不断弹出提示 要信任此电脑吗
  19. Windows 2012 R2服务器的80端口被IIS占用的最好处理办法
  20. 调研人工智能技术在无人驾驶汽车中的应用

热门文章

  1. java curl json_POST请求发送json数据java HttpUrlConnection
  2. 用计算机打出圣诞树,手机计算器圣诞树的祝福输入方式,手机计算器圣诞树获得方法...
  3. 【Spring源码分析】Bean加载流程概览
  4. 关于Xbox live及其在中国的使用
  5. Openstack介绍
  6. 使用一阶微分对图像锐化
  7. 回首经典的SQL Server 2005
  8. 1595 hdu find the longest of the shortest
  9. 风云点评:Flash 与 Silverlight 终极大比拼
  10. Day14作业 一、完成下面的要求? 先创建一个工人类,属性:姓名,年龄,工资