这道题就是根据已给出的数组中的数来判断该数组是不是Valid的,也就是行,列,九宫格中都不能出现相同的数字。
A partially filled sudoku which is valid. 上边的这个数组就是valid的。
The Sudoku board could be partially filled, where empty cells are filled with the character '.'
.
用 '.' 表示空的位置,空的位置跳过就好了。
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
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. 一列里边有两个8,第一个九宫格里边也有两个8,就不是valid。
解:
这道题比较简单,因为只需要判断从给出的数字中有没有出现行,列,或者九宫格中重复的数字即可,这个数组有没有解这道题并不关心。
很直接的想法就是分别看每行,每列,每个九宫格中有没有出现过重复的数字。用unordered_set很容易实现。
bool isValidSudoku(vector<vector<char>>& board)
{
unordered_set<char> setB;
// 判断行
for(int i = 0; i < 9; i++){
setB.clear();
for(int j = 0; j < 9; j++){
if(board[i][j] != '.')
{
if(setB.find(board[i][j]) != setB.end())
return false;
else
setB.insert(board[i][j]);
}
}
}
// 判断列
for(int i = 0; i < 9; i++){
setB.clear();
for(int j = 0; j < 9; j++){
if(board[j][i] != '.')
{
if(setB.find(board[j][i]) != setB.end())
return false;
else
setB.insert(board[j][i]);
}
}
}
// 判断九宫格
for(int i = 0; i < 9; i += 3){
for(int j = 0; j < 9; j += 3){
setB.clear();
for(int x = 0; x < 3; x++){
for(int y = 0; y < 3; y++){
if(board[i + x][j + y] != '.')
{
if(setB.find(board[i + x][j + y]) != setB.end())
return false;
else
setB.insert(board[i + x][j + y]);
}
}
}
}
}
return true;
}
所有的算法都应该是这种思想,判断三种情况下有没有重复的,有的话直接返回false,全判断玩还没有错就返回true。但是有更简便的写法,就是用三个9 * 9数组表示行,列,九宫格中的数字有没有出现过,比如row_appear[1][2] = 1,就表示,第1行中,2出现过了,如果等于0就是没出现过。所以在初始化时需要将三个数组全初始化为0,表示遍历board数组之前,所有数都没有出现过。代码如下:
bool isValidSudoku(vector<vector<char> > &board)
{
// 因为要初始化为0,所以直接就这么写了,否则不行
int row_appear[9][9] = {0}, col_appear[9][9] = {0}, box_appear[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; // 因为行,列,九宫格的数都是 0 ~ 8
int k = i / 3 * 3 + j / 3; // 第几个九宫格
if(row_appear[i][num] || col_appear[j][num] || box_appear[k][num])
return false;
row_appear[i][num] = col_appear[j][num] = box_appear[k][num] = 1;
}
return true;
}
每个数组中的数只有1和0两种可能,a[i][j] = 1(泛指三个数组) 表示这个数组中第 i 行出现过 j 这个数了:
1、如果是表示行的数组,则表示board数组中,第 i 行出现过了 j 这个数;
2、如果是表示列的数组,则表示board数组中,第 i 列出现过了 j 这个数;
3、如果是表示九宫格的数组,则表示board数组中,第 i 个九宫格中出现过了 j 这个数。
九宫格的顺序按照代码中的写法应该是下图。