leetcode36 有效的数独【中等难度】

英文题目: Valid sudoku

难度: 中等

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

  1. 数字 1-9 在每一行只能出现一次。

  2. 数字 1-9 在每一列只能出现一次。

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

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

注意:

  • 一个有效的数独(部分已被填充)不一定是可解的。

  • 只需要根据以上规则,验证已经填入的数字是否有效即可。

示例 1:

img

示例 2:

提示:

  • board.length == 9

  • board[i].length == 9

  • board[i][j] 是一位数字或者 '.'

分析

方法1、蛮力直接法

使用set, 对于行遍历: 每一行中, isValid: unique的数字数量+'.'的数量 = 9, 对于列遍历:每一列中, isValid: unique的数字数量+'.'的数量 = 9, 对于box遍历:每个3行3列九宫格中,isValid: unique的数字数量+'.'的数量 = 9。

已AC代码:

跟国外的小伙伴想到一块去了。 https://leetcode.com/problems/valid-sudoku/discuss/869625/easy-C%2B%2B-with-set

方法2:set插入方法 - 改进

坐标中任意一点(i,j),可以map到对应的的第几行第几列的方块(box)中,box的坐标为(i/3, j/3)。

于是把一个小的九宫格中的数全压缩到一个box中,比如:

是否有插入失败的1

以最中间那个九宫格为例,使用int型的/3可以得到:

是否有插入失败的2

对于任意一个值不为'.'的字符,进行如下操作:

1.把所在row的信息插入到大九宫格中;

2.把所在column的信息插入到大九宫格中;

3.把所在的小方块(box)的信息插入到大九宫格中。

插入如果失败说明出现了重复。

已AC的C++代码:

Java的HashSet有同样的写法,Java中插入失败,会出现 set.Add() == false

方法3:使用位操作

此题,使用位操作,是几种解法中速度最快的算法了。

具体做法是:

方法3

将大数独棋盘分成9个小棋盘,编号0~8。

窗口中的每个小方格若有数字,必为 1 ~ 9 (记作k),该方法适用于 遍历行/遍历列/遍历box。

然后把 二进制数 1 左移 k 位,得到偏移量shift,后续使用按位或|来判断是否存在。

已AC的C++代码:

后两种方法,参考:

https://leetcode-cn.com/problems/valid-sudoku/solution/wei-yun-suan-qiu-jie-you-xiao-shu-du-c-b-sac7/

https://www.youtube.com/watch?v=ceOLAY4XUOw&ab_channel=JacobHuang

最后更新于

这有帮助吗?