题目:
判断一个 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 形式的。
思路:
没看题解之前,我的想法就是横向排除、纵向排除、小方格再排除,这样提交也可以成功。但其实遍历一遍就可以满足需求,关键点在于如何根据当前位置的行列值算出当前位置所在的小方格。仔细观察不难发现i
行j
列的数所在的小方格是:(i/3)*3+j/3
(从0开始编号)。
代码1(遍历一次即可):
这块刚开始犯了一个错误,就是python二维列表的初始化问题。
对于一维列表,初始化可以这样写:test = [0]*9
,这样按索引修改列表是没有问题的。
但是对于二维列表,如果写成test = [[0]*9]*9
就会出现问题,这样的写法相当于把一个[0]*9
复制了9次,本质上他们是同一个[0, 0, 0, 0, 0, 0, 0, 0, 0]
对象,会被同步修改。所以正确初始化二维列表的方法是:
row = [[0] * 9 for i in range(9)]
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
row = [[0] * 9 for i in range(9)]
col = [[0] * 9 for i in range(9)]
box = [[0] * 9 for i in range(9)]
for i in range(len(board)):
for j in range(len(board[i])):
if board[i][j] == ".":
continue
x = int(board[i][j])
if row[i][x-1]:
return False
if col[j][x-1]:
return False
if box[(int(i/3)*3 + int(j/3))][x-1]:
return False
row[i][x-1] = 1
col[j][x-1] = 1
box[(int(i / 3)) * 3 + int(j / 3)][x-1] = 1
return True
代码2(分别判断):
class Solution(object):
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
# 横向排除
for i in range(len(board)):
array = []
for j in range(len(board[i])):
if board[i][j] == ".":
continue
x = int(board[i][j])
if x in array:
return False
else:
array.append(x)
# 纵向排除
for j in range(len(board[0])):
array = []
for i in range(len(board)):
if board[i][j] == ".":
continue
x = int(board[i][j])
if x in array:
return False
else:
array.append(x)
# 3*3小方格排除
l = 3
for jstep in range(l):
for istep in range(l):
array = []
for i in range(l):
for j in range(l):
if board[i + l * istep][j + l * jstep] == ".":
continue
x = int(board[i + l * istep][j + l * jstep])
if x in array:
return False
else:
array.append(x)
return True