依次检查每行,每列,每个子九宫格是否出现重复元素,如果出现返回false,否则返回true.
难点在于表示第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
解法一:维护三个数组来检查数字是否出现过
解题思路:只需要用一个hash表记录每行、每列、每个小矩阵中出现过的 1-9即可。这里我用一个 int 的0-8位的值来表示数字1-9是否出现过, 当数字i出现时, 就将第i-1位标记为1。
Three flags are used to check whether a number appear.
used1: check each row
used2: check each column
used3: check each sub-boxes
class Solution
{
public:
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;
}
};
解法二:
// LeetCode, Valid Sudoku
// 时间复杂度 O(n^2),空间复杂度 O(1)
class Solution {
public:
bool isValidSudoku(const vector<vector<char>>& board) {
bool used[9];
for (int i = 0; i < 9; ++i) {
fill(used, used + 9, false);
for (int j = 0; j < 9; ++j) // 检查行
if (!check(board[i][j], used))
return false;
fill(used, used + 9, false);
for (int j = 0; j < 9; ++j) // 检查列
if (!check(board[j][i], used))
return false;
}
for (int r = 0; r < 3; ++r) // 检查 9 个子格子
for (int c = 0; c < 3; ++c) {
fill(used, used + 9, false);
for (int i = r * 3; i < r * 3 + 3; ++i)
for (int j = c * 3; j < c * 3 + 3; ++j)
if (!check(board[i][j], used))
return false;
}
return true;
}
bool check(char ch, bool used[9]) {
if (ch == '.') return true;
if (used[ch - '1']) return false;
return used[ch - '1'] = true;
}
};
解法三:
class Solution {
public:
bool isValidSudoku(vector<vector<char> > &board) {
for(int i = 0; i < 9; i ++)
{
unordered_map<char, bool> m1; //check i_th row
unordered_map<char, bool> m2; //check i_th column
unordered_map<char, bool> m3; //check i_th subgrid
for(int j = 0; j < 9; j ++)
{
if(board[i][j] != '.')
{
if(m1[board[i][j]] == true)
return false;
m1[board[i][j]] = true;
}
if(board[j][i] != '.')
{
if(m2[board[j][i]] == true)
return false;
m2[board[j][i]] = true;
}
if(board[i/3*3+j/3][i%3*3+j%3] != '.')
{
if(m3[board[i/3*3+j/3][i%3*3+j%3]] == true)
return false;
m3[board[i/3*3+j/3][i%3*3+j%3]] = true;
}
}
}
return true;
}
};