36. Valid Sudoku
Leetcode Hash Table题目¶
Determine if a 9x9 Sudoku board is valid. Only the filled cells need to be validated according to the following rules:
- Each row must contain the digits
1-9
without repetition. - Each column must contain the digits
1-9
without repetition. - Each of the 9
3x3
sub-boxes of the grid must contain the digits1-9
without repetition.
A partially filled sudoku which is valid.
The Sudoku board could be partially filled, where empty cells are filled with the character .
.
Example 1:
Input:
[
["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"]
]
Output: true
Example 2:
Input:
[
["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"]
]
Output: false
Explanation: Same as Example 1, except with the 5 in the top left corner being modified to 8. Since there are two 8's in the top left 3x3 sub-box, it is invalid.
Note:
- A Sudoku board (partially filled) could be valid but is not necessarily solvable.
- Only the filled cells need to be validated according to the mentioned rules.
- The given board contain only digits 1-9 and the character '.'.
- The given board size is always 9x9.
思路¶
利用hash table(这里是字典),识别是否出现数字重复。利用numpy方便处理矩阵元素。
class Solution(object):
def no_repetation(self, alist):
n = len(alist)
mydict = {"1":0,"2":0,"3":0, "4":0,"5":0, "6":0, "7":0, "8":0, "9":0}
for x in alist:
if x == '.':
continue
if mydict[x] == 0:
mydict[x] = 1
else:
return False
return True
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
import numpy as np
import copy
myboard = np.array(board)
for i in range(9):
# Each row, column must contain the digits 1-9 without repetition.
eachrow = myboard[i,:]
repetation = self.no_repetation(eachrow)
if not repetation:
return False
# Each row, column must contain the digits 1-9 without repetition.
eachcolumn = myboard[:,i]
repetation = self.no_repetation(eachcolumn)
if not repetation:
return False
# Each of the 9 3x3 sub-boxes of the grid must contain the digits 1-9 without repetition.
for i in range(3):
for j in range(3):
eachblock = myboard[i*3:(i+1)*3, j*3:(j+1)*3].reshape((-1,))
repetation = self.no_repetation(eachblock)
if not repetation:
return False
return True
还有一种更巧妙的方法,就是每一行、每一列、每一块都是一个字典预先放在列表中;并且对于块的处理,巧妙的利用矩阵元素的行列数计算所在的块:
class Solution:
def isValidSudoku(self, board):
"""
:type board: List[List[str]]
:rtype: bool
"""
dic_row = [{},{},{},{},{},{},{},{},{}]
dic_col = [{},{},{},{},{},{},{},{},{}]
dic_box = [{},{},{},{},{},{},{},{},{}]
for i in range(len(board)):
for j in range(len(board)):
num = board[i][j]
if num == ".":
continue
if num not in dic_row[i] and num not in dic_col[j] \\
and num not in dic_box[3*(i//3)+(j//3)]:
dic_row[i][num] = 1
dic_col[j][num] = 1
dic_box[3*(i//3)+(j//3)][num] = 1
else:
return False
return True
对应的C++版本为:
bool isValidSudoku(vector<vector<char> > &board)
{
int used1[9][9] = {0}, used2[9][9] = {0}, used3[9][9] = {0};
for(int i = 0; i < board.size(); ++ i)
for(int j = 0; j < board[i].size(); ++ j)
if(board[i][j] != '.')
{
int num = board[i][j] - '0' - 1, k = i / 3 * 3 + j / 3;
if(used1[i][num] || used2[j][num] || used3[k][num])
return false;
used1[i][num] = used2[j][num] = used3[k][num] = 1;
}
return true;
}