36. 有效的数独 [media]
36. 有效的数独 [media]
https://leetcode-cn.com/problems/valid-sudoku
判断一个 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 形式的。
通过次数76,938 | 提交次数128,659
Second Try
参考题解用的小技巧,把matrix的编码写入一个循环中搞定,matrix的定位是一个小技巧,通过观察实现的。
rows, collumns,matrix都统一使用defaultdict的统计功能,其实相当于又把整个矩阵保存了三遍。
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
关键是小矩阵里: i // 3 , j // 3相等的,就在同一个小矩阵里(0-2, 3-5,6-8竟然刚刚好,如果是1-9的反而不好处理,1-3,4-6,7-9)
按行遍历,总共9个列表需要安全;按列遍历,也是9个列表需要安全
关于矩阵如何定位有点麻烦,总共9个小矩阵,从0到9的位置排列刚好可以用自己的坐标来完成, row * 3 + columns, 刚刚好,属于观察得到的结论。
matrix_idx = [(0, 0),(0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
"""
rows = [collections.defaultdict(int) for _ in range(9)]
collumns = [collections.defaultdict(int) for _ in range(9)]
matrix = [collections.defaultdict(int) for _ in range(9)]
for r in range(9):
for c in range(9):
t = board[r][c]
if t == ".":
continue
rows[r][t] += 1
collumns[c][t] += 1
matrix[r // 3 * 3 + c // 3][t] += 1
if any([rows[r][t] > 1, collumns[c][t] > 1, matrix[r // 3 * 3 + c // 3][t]> 1]):
return False
return True
- 执行用时:32 ms, 在所有 Python 提交中击败了98.54%的用户
- 内存消耗:12.7 MB, 在所有 Python 提交中击败了11.11%的用户
First Try
一开始不知道有什么高级内容,看了一会儿觉得还是直接用暴力破解,竟然也通过了,成绩还可以。 不过就算有了思路,在写的时候竟然也是出现了一堆bug,调了一会儿,还是写得不够多。矩阵类的对某一行进行统计和对某一列进行统计难易程度是不同的,还好额外使用了空间把行列倒换来一波,事情就简单了许多。小矩阵的化,则是直接使用range进行跳转。
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
def check_valid(matrix):
clear_matrix = list(filter(lambda x: x!= ".", matrix))
return len(clear_matrix) == len(set(clear_matrix))
flag = True
reverse_board = [[board[i][j] for i in range(9)] for j in range(9)]
for i in range(9):
if (not check_valid(board[i])) or (not check_valid(reverse_board[i])):
flag = False
break
if not flag:
return False
for i in range(0, 7, 3):
if not flag:
break
for j in range(0, 7, 3):
matrix = [board[i + r][j + c] for r in range(0, 3) for c in range(0, 3)]
if not check_valid(matrix):
flag = False
break
return flag
- 执行用时 :52 ms, 在所有 Python 提交中击败了50.53%的用户
- 内存消耗 :12.7 MB, 在所有 Python 提交中击败了11.11%的用户