请判定一个数独是否有效。
该数独可能只填充了部分数字,其中缺少的数字用 .
表示。
样例
The following partially filed sudoku is valid.
解题思路:
验证数独是否有效,就三个要求:
1.数字1-9在每一行最多只能出现一次
2.数字1-9在每一列最多只能出现一次
3.数字1-9在每一个3*3九宫格内最多只能出现一次
出现有次数的题目,一般采用哈希表,所以我们只需要检查每一行,每一列,每个九宫格中数字出现的次数即可,分别用三个哈希表存储。
难点在于表示第i个九宫格每个格点的坐标。
观察行号规律:
第0个九宫格:000111222; 第1个九宫格:000111222; 第2个九宫格:000111222;
第3个九宫格:333444555; 第4个九宫格:333444555; 第5个九宫格:333444555;
第6个九宫格:666777888; 第7个九宫格:666777888; 第8个九宫格:666777888;
可见对于每三个九宫格行号增3;对于单个九宫格,每三个格点行号增1。
因此第i个九宫格的第j个格点的行号可表示为i/3*3+j/3
观察列号规律:
第0个九宫格:012012012; 第1个九宫格:345345345; 第2个九宫格:678678678;
第3个九宫格:012012012; 第4个九宫格:345345345; 第5个九宫格:678678678;
第6个九宫格:012012012; 第7个九宫格:345345345; 第8个九宫格:678678678;
可见对于下个九宫格列号增3,循环周期为3;对于单个九宫格,每个格点行号增1,周期也为3。
周期的数学表示就是取模运算mod。
因此第i个九宫格的第j个格点的列号可表示为i%3*3+j%3
class Solution {
public:
/**
* @param board: the board
* @return: whether the Sudoku is valid
*/
bool isValidSudoku(vector<vector<char>> &board)
{
// write your code here
for(int i=0;i<board.size();i++)
{
unordered_map<char,int> m_row;
unordered_map<char,int> m_col;
unordered_map<char,int> m_san;
for(int j=0;j<board[i].size();j++)
{
if(board[i][j] != '.' && ++m_row[board[i][j]] > 1)//检查每一行的元素是否重复
return false;
if(board[j][i] != '.' && ++m_col[board[j][i]] > 1)//检查每一列的元素是否重复
return false;
if(board[i/3*3+j/3][i%3*3+j%3] != '.' &&
++m_san[board[i/3*3+j/3][i%3*3+j%3]] > 1)//检查每个九宫格的元素是否重复
return false;
}
}
return true;
}
};
如果还是不能理解上面九宫格的下标算法,可以直接重新遍历即可,如下:
public class Solution {
/**
* @param board: the board
* @return: whether the Sudoku is valid
*/
public boolean isValidSudoku(char[][] board) {
// write your code here
if(board == null || board.length == 0 || board[0].length == 0)
return true;
int row = board.length;
int col = board[0].length;
//检查横排
for(int i=0; i<row; i++){
Set<Character> set = new HashSet<>();
for(int j=0; j<col; j++){
if(board[i][j] == '.')
continue;
if(set.contains(board[i][j]))
return false;
else
set.add(board[i][j]);
}
}
//检查竖排
for(int j=0; j<col; j++){
Set<Character> set = new HashSet<>();
for(int i=0; i<row; i++){
if(board[i][j] == '.')
continue;
if(set.contains(board[i][j]))
return false;
else
set.add(board[i][j]);
}
}
//检查3*3
for(int i=0; i<row; i=i+3){
for(int j=0; j<col; j=j+3){
Set<Character> set = new HashSet<>();
for(int m=i; m<row && m<i+3; m++){
for(int n=j; n<col && n <j+3; n++){
if(board[m][n] == '.')
continue;
if(set.contains(board[m][n]))
return false;
else
set.add(board[m][n]);
}
}
}
}
return true;
}
}