タイトル
https://leetcode-cn.com/problems/valid-sudoku/
9x9の数独が有効かどうかを判断します。入力した番号が以下のルールに従って有効かどうかを確認するだけで済みます。
1から9までの数字は、1行に1回しか表示できません。
1〜9の数字は、各列に1回だけ表示できます。
1〜9の数字は、太い実線で区切られた各3x3の家に1回だけ表示されます。
上の写真は部分的に塗りつぶされた効果的な数独です。
数独部分のスペースは数字で埋められており、空白スペースは「。」で示されています。
例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の宮殿には2つの8があるので、この数独は無効です。
説明:
有効な数独(部分的に埋められている)は必ずしも解決可能ではありません。
入力した番号が上記のルールに従って有効かどうかを確認するだけです。
指定された数独シーケンスには、1〜9の数字と文字「。」のみが含まれています。
特定の数独は常に9x9の形式です。
問題解決のアイデア
-
ナイーブの考え方は、行、列、および9つのグリッドで個別に検証することであり、ループの数は3 9 * 9です。
-
以下のコードを参照してください
naive version
。 -
観察後、行、列、および9グリッドグリッドに表示された数値は、実際にはコレクションを通じて格納できるため、9 * 9サイクルのみが必要であることがわかります。
-
以下のコードを参照してください
optimized version
。 -
さらに、set()を使用しない、代わりに配列を使用する、ストレージにビットを使用するなど、他の最適化方法もあります。
コード
# - naive version
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
# - check for each row
for row in range(9):
exist_set = set()
for col in range(9):
c = board[row][col]
if c == '.': continue
if c in exist_set:
return False
else:
exist_set.add(c)
# - check for each col
for col in range(9):
exist_set = set()
for row in range(9):
c = board[row][col]
if c == '.': continue
if c in exist_set:
return False
else:
exist_set.add(c)
# - check for each grid
for gr in range(3):
for gc in range(3):
exist_set = set()
for j in range(3):
for i in range(3):
c = board[gr*3 + j][gc*3 + i]
if c == '.': continue
if c in exist_set:
return False
else:
exist_set.add(c)
return True
# - optimized version
class Solution:
def isValidSudoku(self, board: List[List[str]]) -> bool:
row_state_list = [set() for _ in range(9)]
col_state_list = [set() for _ in range(9)]
grid_state_list = [set() for _ in range(9)]
# - check for each cell
for row in range(9):
for col in range(9):
c = board[row][col]
if c == '.': continue
grid_index = (row//3)*3 + col//3
if c in row_state_list[row]: return False
if c in col_state_list[col]: return False
if c in grid_state_list[grid_index]: return False
row_state_list[row].add(c)
col_state_list[col].add(c)
grid_state_list[grid_index].add(c)
return True