Valid Sudoku
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules.
The Sudoku board could be partially filled, where empty cells are filled with the character ‘.’.
A partially filled sudoku which is valid.
Note:
A valid Sudoku board (partially filled) is not necessarily solvable. Only the filled cells need to be validated.
解题思路
按行,按列,再按 3∗3 的九宫格检查,只要都通过就返回true,不然就是false。代码如下:
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
bool used[10];
// 检测9行
for (int i = 0; i < 9; ++i) {
memset(used, 0, sizeof(used));
for (int j = 0; j < 9; ++j) {
char op = board[i][j];
if (op != '.') {
if (used[op - '0']) {
return false;
}
used[op -'0'] = true;
}
}
}
// 检测9列
for (int i = 0; i < 9; ++i) {
memset(used, 0, sizeof(used));
for (int j = 0; j < 9; ++j) {
char op = board[j][i];
if (op != '.') {
if (used[op - '0']) {
return false;
}
used[op -'0'] = true;
}
}
}
// 检测9个九宫格
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
memset(used, 0, sizeof(used));
for (int m = 3 * i; m < 3 * i + 3; ++m) {
for (int n = 3 * j; n < 3 * j + 3; ++n) {
char op = board[n][m];
if (op != '.') {
if (used[op - '0']) {
return false;
}
used[op -'0'] = true;
}
}
}
}
}
return true;
}
};
两重循环的简化版本:如果把九宫格按照行从0开始标号,那么数字board[i][j] 位于第 i/3∗3+j/3 个九宫格内。
bool isValidSudoku(vector<vector<char> > &board) {
vector<vector<bool>> rows(9, vector<bool>(9,false));
vector<vector<bool>> cols(9, vector<bool>(9,false));
vector<vector<bool>> blocks(9, vector<bool>(9,false));
for(int i = 0; i < 9; i++)
for(int j = 0; j < 9; j++)
{
if(board[i][j] == '.')continue;
int num = board[i][j] - '1';
if(rows[i][num] || cols[j][num] || blocks[i - i%3 + j/3][num])
return false;
rows[i][num] = cols[j][num] = blocks[i - i%3 + j/3][num] = true;
}
return true;
}
针对上面的算法,还可以优化空间。上面的算法中,在双重循环时,我们默认了第一重循环表示矩阵的行、第二重循环表示矩阵的列。可以换一种思路:
- 在检测行是否合法时,
i
表示矩阵的行,
j 表示矩阵的列; - 检测列是否合法时,
i
表示矩阵的列,
j 表示矩阵的行; - 检测九宫格是否合法时,
i
表示九宫格的标号,
j 表示九宫格里的每个元素(只是我们需要根据 i 、j 定位相应的元素到原来的矩阵: 第 i 个九宫格里面的第j 个元素在原矩阵的第 3∗(i/3)+j/3 行,第 3∗(i%3)+j%3) 列 ,“/” 表示整数除法)
代码如下:
class Solution {
public:
bool isValidSudoku(vector<vector<char> > &board) {
int rowValid[10] = {0};//用于判断某一行是否合法
int columnValid[10] = {0};//用于判断某一列是否合法
int subBoardValid[10] = {0};//用于判断某一个九宫格是否合法
for(int i = 0; i < 9; i++)
{
memset(rowValid, 0, sizeof(rowValid));
memset(columnValid, 0, sizeof(columnValid));
memset(subBoardValid, 0, sizeof(subBoardValid));
for(int j = 0; j < 9; j++)
{
if(!checkValid(rowValid, board[i][j]-'0') ||
!checkValid(columnValid, board[j][i]-'0') ||
!checkValid(subBoardValid, board[3*(i/3) + j/3][3*(i%3) + j%3]-'0'))
return false;
}
}
return true;
}
bool checkValid(int vec[], int val)
{
if(val < 0)return true;//对应的是字符‘.’
if(vec[val] == 1)return false;
vec[val] = 1;
return true;
}
};