题目描述

判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。

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

上图是一个部分填充的有效的数独。
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

示例 1:
输入:
[
[“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”]
]
输出: true
示例 2:
输入:
[
[“8”,“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”]
]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。
说明:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字 1-9 和字符 ‘.’ 。
给定数独永远是 9x9 形式的。

初步思路:

这个题的思路还是挺明确的,不管是采用暴力的方式还是什么方式,无非就是三个判断,我遍历数组,只要保证每一行没有重复的,每一列没有重复的,每一个九宫格没有重复的,那么这个就是有效数独。
所以,我得第一次解法是

这个题初步想法写三个判断法则
1. 遍历行
每一行, 建一个map用来统计数的个数,如果不是1, 返回false
2. 遍历列
每一列,和行的思路一样
3. 遍历每个九宫格
九宫格的遍历有点复杂,初步想法就是把九宫格中心的坐标先以键值对的形式存入数组,然后遍历数组,对每一个九宫格,建一个map统计当前九宫格里面出现的数字数量,如果大于1,返回false。 即用九宫格中心的那个点代表一个九宫格。

所以就根据上述的思想完成了第一个版本的代码如下:

class Solution
{public:bool isValidSudoku(vector<vector<char> >& board){int rowsize = board.size();int colsize = board[0].size();// 遍历每一行,不能有重复的for (int i=0; i<rowsize; i++){map<char, int> m;map<char, int> ::iterator it;for (int j=0; j<colsize; j++){if (board[i][j] != '.'){m[board[i][j]]++;}}for (it=m.begin(); it!=m.end(); it++){if (it->second >1)return false;}}// 遍历每一列,不能有重复的for (int i=0; i<colsize; i++){map<char, int>m;map<char, int> ::iterator it;for (int j=0; j<rowsize; j++){if (board[j][i] != '.'){m[board[j][i]] ++;}}for (it=m.begin(); it!=m.end(); it++){if (it->second >1)return false;}}// 遍历每个九宫格// 先建立一个二维数组,把每个九宫格的中心坐标找好int loc[] = {1, 1,1, 4,1, 7,4, 1,4, 4,4, 7,7, 1,7, 4,7, 7};for (int i=0; i<17; i+=2){// 获取九空格的中心坐标int locrownum = loc[i];int loccolnum = loc[i+1];// 每一个九空格,判断是否有重复的数字map<char, int> m;if( board[locrownum-1][loccolnum-1] != '.'){m[board[locrownum-1][loccolnum-1]]++;}if(board[locrownum-1][loccolnum] != '.'){m[board[locrownum-1][loccolnum]]++;}if(board[locrownum-1][loccolnum+1] != '.'){m[board[locrownum-1][loccolnum+1]]++;}if(board[locrownum][loccolnum-1] != '.'){m[board[locrownum][loccolnum-1]]++;}if(board[locrownum][loccolnum] != '.'){m[board[locrownum][loccolnum]]++;}if(board[locrownum][loccolnum+1] != '.'){m[board[locrownum][loccolnum+1]]++;}if(board[locrownum+1][loccolnum-1] != '.'){m[board[locrownum+1][loccolnum-1]]++;}if(board[locrownum+1][loccolnum] != '.'){m[board[locrownum+1][loccolnum]]++;}if(board[locrownum+1][loccolnum+1] != '.'){m[board[locrownum+1][loccolnum+1]]++;}// 弄一个迭代器,进行有效区分map<char, int> ::iterator it;for (it=m.begin(); it!=m.end(); it++){if (it->second >1)return false;}}return true;}
};

这个代码A掉这个题目没有任何问题,但是太繁琐了,尤其是九宫格那竟然能写九遍判断也是没谁了,完全是暴力思想了。 所以看了看人家的题解,对这个题做了一个优化,没想到两次循环遍历一遍就可以看出是不是有效数独。

改进思路:

思想依然是同样的思想,但是在效率上有了提高,就是我用一次遍历所有的元素就可以判断出是不是有效数独。 这里的关键是弄清楚每一个子数独和整个数独的坐标关系:借助官方的图来理解:

看上面这个图,99的一个大数独是由9个33的小数独组成的,编号0-8,那么遍历大数独的时候,i, j与每一个小数独的编号的关系是

box_index = (i / 3) * 3 + j / 3

所以基于这个关系式,就可以写思路了:

首先,我要见三个9行10列的二维数组,每一个统计行,列,子宫格里面元素的出现的次数
然后,遍历这个大数独, 对于出现的每一个元素,如果不是".",那么相应的统计个数的数组相应的位置就进行加1, 如果发现重复了,返回false。

思路看着还是有点晕乎,看代码吧。

class Solution
{public:bool isValidSudoku(vector<vector<char> >& board){// 建立三个9行10列(0-9)的二维数组统计个数vector<vector<int> > rows(9, vector<int>(10, 0));  // 9行的每一行是否有重复的   vector<vector<int> > cols(9, vector<int>(10, 0));  // 9列的每一列里面是否有重复的vector<vector<int> > cell(9, vector<int>(10, 0));  // 9个子宫格的每一个子宫格里面有没有重复的(注意,这里得经过那个i,j的映射)for (int i = 0; i < 9; ++i){for (int j = 0; j < 9; ++j){if(board[i][j] != '.'){int e = board[i][j] - '0';// 判断行中是否有重复的if (rows[i][e] == 0)rows[i][e]++;elsereturn false;// 判断列中是否有重复的if (cols[j][e] == 0)cols[j][e]++;elsereturn false;// 判断小的九宫格里面是否有重复的int ci = map(i, j);if (cell[ci][e] == 0)cell[ci][e]++;elsereturn false;}}}return true;}int map(int i, int j){int a = i / 3;int b = j / 3;return a*3 + b;}
};

小总一下:

这个题总体上思路比较清晰,开门见山,但是操作起来,如果不知道那个子宫格和整体的数独之间的那个对应关系的话,很难想到后面的改进思路这一个,通过一次遍历就判断出来,所以还是挺佩服我第一种解法的,这次以解决问题为根本目标了,好与坏,先解决出来再说。其次就是学到了vector创建二维数组并且使用的技巧,并且通过资料整理了一下:
https://blog.csdn.net/wuzhongqiang/article/details/103213734
PS: 这个题看过题解之后,发现还有一种位运算的解法,看了很长时间没怎么看明白,就先不整理了,可以参考一下:

https://leetcode-cn.com/problems/valid-sudoku/solution/java-wei-yun-suan-xiang-jie-miao-dong-zuo-biao-bia/

LeetCode初级算法之数组:有效数独相关推荐

  1. LeetCode初级算法之数组:36 有效数独

    01 题目描述 判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. 数字 1-9 在每一行只能出现一次. 数字 1-9 在每一列只能出现一次. 数字 1-9 在每一 ...

  2. LeetCode初级算法(数组)解答

    这里记录了LeetCode初级算法中数组的一些题目: 加一 本来想先转成整数,加1后再转回去:耽美想到测试的例子考虑到了这个方法的笨重,所以int类型超了最大范围65536,导致程序出错. class ...

  3. LeetCode_初级算法_数组

    LeetCode|初级算法_数组 题目如下: 1.1 从排序数组中删除重复项 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间 ...

  4. leetcode初级算法4.两个数组的交集 II

    leetcode初级算法4.两个数组的交集 II 仅为个人刷题记录,不提供解题思路 题解与收获 我的解法:(总结在代码中) public int[] intersect(int[] nums1, in ...

  5. leetcode初级算法5.加一

    leetcode初级算法5.加一 仅为个人刷题记录,不提供解题思路 题解与收获 我的解法:(总结在代码中) public int[] plusOne(int[] digits) {//获取digits ...

  6. Leetcode 初级算法 - 设计问题

    Leetcode 初级算法 - 设计问题 原始地址:https://github.com/jerrylususu/leetcode-easy 二级标题格式:[章节内题号] [题库内题号] [题目标题] ...

  7. leetcode初级算法6.字符串转整数(atoi)

    leetcode初级算法6.字符串转整数(atoi) 仅为个人刷题记录,不提供解题思路 题解与收获 我的解法: public int myAtoi(String s) {//避免魔法值先设spaceS ...

  8. leetcode初级算法4.只出现一次的数字

    leetcode初级算法4.只出现一次的数字 仅为个人刷题记录,不提供解题思路 题解与收获 我的解法: public static int singleNumber(int[] nums) {if(n ...

  9. leetcode初级算法3.存在重复元素

    leetcode初级算法3.存在重复元素 仅为个人刷题记录,不提供解题思路 题解与收获 我的解法: Arrays.sort(nums);for(int i = 0; i < nums.lengt ...

最新文章

  1. xml批量修改php,通过php修改xml文档内容的方法
  2. js 移动端 滑块验证码插件_VUE技术详解,Vue.js从入门到精通
  3. byte转换int时为何与0xff进行与运算
  4. mysql group 条件_mysql 的group by 满足的规则要求:
  5. 【Java】扑克牌の顺子Judge
  6. python的empty函数_python中numpy.empty()函数的用法
  7. 阿里巴巴公布了一份最新的AI成绩单
  8. resample函数_使用Pandas的resample函数处理时间序列数据的技巧
  9. 远程控制软件用户群分析
  10. JNDI配置数据库连接
  11. python笔记(求100偶数的和)
  12. 长路漫漫,唯剑作伴--基础
  13. orbslam2+azure kinect DK稠密重建
  14. STM32 Keil安装和配置
  15. CSS基础--属性设置
  16. 互联网金融系统技术沙龙:小米风控实践
  17. 复合文档格式(一)- Excel XLS文件格式
  18. go的close函数理解
  19. spark推测执行 优点 缺点
  20. PHP实现站内信设计思路与方案

热门文章

  1. NLP自然语言处理CRF详解
  2. 央企招聘:中储粮集团2023公开招聘公告(校招+社招,共700人)
  3. 模型预测控制(MPC)解析(六):有约束的MPC简介
  4. (10.2.1)15款优秀移动APP产品原型设计工具
  5. 英语人机考试计算机算分吗,揭秘 | 英语“人机对话”听说考试提分策略 注意事项,收藏备用 !...
  6. cta 音频测试_CTA测试介绍.pdf
  7. 校本课程——宝宝爱上学
  8. k折交叉验证优缺点_都说K折交叉验证最常见,你会做吗?
  9. 第九周项目四----广义表算法库及应用1
  10. 老字号“张小泉”上线小程序与酷客多达成战略合作!