每天一道LeetCode-----数独盘求解
Valid Sudoku
原题链接Valid Sudoku
判断给定的数独盘是否有效,数独盘中可能有空位置。
简述一下数独的规则,参考连接Sudoku Puzzles - The Rules.
- 每一行,数字1-9只能出现一次
- 每一列,数字1-9只能出现一次
- 每个3 * 3方格中,数字1-9只能出现一次。这里3 * 3方格只包括9个,即图片中加粗黑线分开的9个方格
其实就是每个点只能存在1-9这九个数字中的一个,满足每一行,每一列,每个3 * 3方格不能出现重复的数字
判断一个数独盘是否有效,只需要判断是否满足上述三个规则即可。另外,如果给出的数独盘像图片那样有些地方没有填充数字,也没有关系。只需要判断有数字的部分就好,比如说第一行只有5, 3, 7,那么可以判断第一行没有出现重复的数字,是满足规则一的。
肯定需要全部遍历一遍,每遍历到一个位置,就判断它所在的行,所在的列,所在的3 * 3方格是否已经存在同样的数字了,如果存在,返回false,否则,将这个数字添加到行,列,3 * 3方格的记录中。
所以需要分别记录每一行,每一列,每一个3 * 3方格都有那些数字出现过,其实就是3个二维数组
- 记录每一行都出现了哪些数字,
vector<vector<int>> rows(9, vector<int>(10, 0));
- 记录每一列都出现了哪些数字,
vector<vector<int>> columns(9, vector<int>(10, 0));
- 记录每个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
- rows[i][n]表示第i行出现数字n的个数,不是1就是0
- columns[j][n]表示第j列出现数字n的个数,不是1就是0
- 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-9只能出现一次
- 每一列,数字1-9只能出现一次
- 每个3 * 3方格中,数字1-9只能出现一次。这里3 * 3方格只包括9个,即图片中加粗黑线分开的9个方格
对于某个空格,它所能填充的数字需要满足
- 在所在行没有出现过的
- 在所在行没有出现过的
- 在所在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-----数独盘求解相关推荐
- leetcode17. 电话号码的字母组合--每天刷一道leetcode算法系列!
作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...
- 数独游戏求解:解法适用于任意阶数的数独
0.数独简介 数独(すうどく,Sūdoku)是一种运用纸.笔进行演算的逻辑游戏.以九阶数独为例,玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行.每一列.每一个粗线宫内的数字 ...
- leetcode最小面积_每日一道 LeetCode (51):盛最多水的容器
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- atoi函数_每日一道 LeetCode (50):字符串转换整数 (atoi)
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 去掉数组最后一个元素_leetcode 34. 在排序数组中查找元素的第一个和最后一个位置每天刷一道leetcode算法系列!...
作者:reed,一个热爱技术的斜杠青年,程序员面试联合创始人 前文回顾: leetcode1. 两数之和--每天刷一道leetcode系列! leetcode2. 两数相加--每天刷一道leetcod ...
- 二叉树层次遍历c语言_每日一道 LeetCode (23):二叉树的层次遍历 II
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- c++两个数组对比去掉重复的元素_每日一道 LeetCode (8):删除排序数组中的重复项和移除元素...
❝ 每天 3 分钟,走上算法的逆袭之路. ❞ 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub:https://github.com/meteor1993/LeetCode Gi ...
- 【python】一道LeetCode搞懂递归算法!#131分割回文串 #以及刷LeetCode的一点点小心得 [数据结构与算法基础]
题目:给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串.返回 s 所有可能的分割方案. # 示例 输入: "aab" 输出: [["aa",&q ...
- 每日一道 LeetCode (16):求 x 的平方根
每天 3 分钟,走上算法的逆袭之路. 前文合集 每日一道 LeetCode 前文合集 代码仓库 GitHub: https://github.com/meteor1993/LeetCode Gitee ...
最新文章
- 基于持久内存的 单机上亿(128B)QPS -- 持久化 k/v 存储引擎
- C#语言与面向对象技术(5)
- php之前代码,PHP语法检查源代码前控制
- linux比较10个文件是否一致,Linux中文件管理--cmp--比较两个文件是否有差异
- [USACO08MAR]土地征用Land Acquisition
- 计算机软件uml,[计算机软件及应用]UML.ppt
- FLASH闪存原理与实验
- SceneBuilder中文版
- html怎么取消打印空白页,怎么取消打印空白页:如何删除Excel工作表中的空白页...
- RxView学习及实现按钮防抖功能
- 【线性代数】上三角矩阵/下三角矩阵
- html页面中艺术字,html 生成艺术字
- QQ邮箱账号异常登录
- PS之基础知识汇总(总结版)
- 2018CSTC web2 writeup
- 机器翻译古文也翻车?读了20次“苟富贵勿相忘”后,谷歌:没钱的人总会被遗忘...
- Android PULL XML Praser
- mac不断弹出提示 要信任此电脑吗
- Windows 2012 R2服务器的80端口被IIS占用的最好处理办法
- 调研人工智能技术在无人驾驶汽车中的应用
热门文章
- java curl json_POST请求发送json数据java HttpUrlConnection
- 用计算机打出圣诞树,手机计算器圣诞树的祝福输入方式,手机计算器圣诞树获得方法...
- 【Spring源码分析】Bean加载流程概览
- 关于Xbox live及其在中国的使用
- Openstack介绍
- 使用一阶微分对图像锐化
- 回首经典的SQL Server 2005
- 1595 hdu find the longest of the shortest
- 风云点评:Flash 与 Silverlight 终极大比拼
- Day14作业 一、完成下面的要求? 	先创建一个工人类,属性:姓名,年龄,工资