36. Valid Sudoku
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 digits 1-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.
方法1: 3 次遍历
basketking:https://www.youtube.com/watch?v=iqe1JSjyldo
思路:
进行rowwise,colwise,cubewise的三次遍历,每次用一个set记住当前row/col/cube出现过哪些数字,一旦出现重复return false 就可以了。这个题的关键是怎么转换成cube的坐标:把i堪称在大九宫格中的循环,j在每一个小九宫格中的循环,他们全部需要按照 (num / 3, num % 3)的顺序完成。因此只需要对i , j 取函数:
r = ( i / 3) * 3 + (j / 3)
c = (i % 3) * 3 + (j % 3)
即为转换到cubewise遍历的坐标。
易错点
- 上面的转换:为什么要把 (i / 3)或者(i%3)再*3呢?因为每次i的变化是对于大九宫格,相当于向右或向下一次性前进3格。
- set更新的位置
- 要判断当前点是否是’.’:是的话跳过不作处理
Complexity
Time complexity: O(n^2)
Space complexity: O(1)
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
for (int i = 0; i < 9; i++){
set<int> row;
for (int j = 0; j < 9; j ++){
if (row.find(board[i][j]) != row.end()) return false;
if (board[i][j] != '.')
row.insert(board[i][j]);
}
}
for (int j = 0; j < 9; j++){
set<int> col;
for (int i = 0; i < 9; i ++){
if (col.find(board[i][j]) != col.end()) return false;
if (board[i][j] != '.')
col.insert(board[i][j]);
}
}
for (int i = 0; i < 9; i++){
set<int> cube;
for (int j = 0; j < 9; j ++){
int r = (i / 3 ) * 3 + j / 3 ;
int c = (i % 3 ) * 3 + j % 3;
if (cube.find(board[r][c]) != cube.end()) return false;
if (board[r][c] != '.')
cube.insert(board[r][c]);
}
}
return true;
}
};
// i = 0, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (0, 0), (0, 1), (0, 2), (1, 0), (1, 1) , (1, 2), (2, 0), (2, 1), (2, 2)
// i = 1, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (0, 3), (0, 4), (0, 5), (1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)
// i = 2, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (0, 6), (0, 7), (0, 8), (1, 6), (1, 7), (1, 8), (2, 6), (2, 7), (2, 8)
// i = 3, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (3, 0), (3, 1), (3, 2), (4, 0), (4, 1) , (4, 2), (5, 0), (5, 1), (5, 2)
// i = 4, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (3, 3), (3, 4), (3, 5), (4, 3), (4, 4) , (4, 5), (5, 3), (5, 4), (5, 5)
// i = 5, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (3, 6), (3, 7), (3, 8), (4, 6), (4, 7) , (4, 8), (5, 6), (5, 7), (5, 8)
// i = 6, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (6, 0), (6, 1), (6, 2), (7, 0), (7, 1) , (7, 2), (8, 0), (8, 1), (8, 2)
// i = 7, j = 0 , 1, 2, 3, 4, 5, 6, 7, 8
// (6, 3), (6, 4), (6, 5)
方法2: 1次遍历
YRB: https://www.cnblogs.com/yrbbest/p/4436318.html
思路:
不用把i 和 j 当成行列坐标,可以用下面的函数转化一次性在三个set里面都check一次。
Complexity
Time complexity: O(n^2)
Space complexity: O(1)
class Solution {
public:
bool isValidSudoku(vector<vector<char>>& board) {
for (int i = 0; i < 9; i++){
set<int> row;
set<int> col;
set<int> cube;
for (int j = 0; j < 9; j ++){
// row
if (board[i][j] != '.' && row.find(board[i][j]) != row.end()) return false;
else row.insert(board[i][j]);
// col
if (board[j][i] != '.' && col.find(board[j][i]) != col.end()) return false;
else col.insert(board[j][i]);
// cube
int r = (i / 3) * 3 + (j / 3);
int c = (i % 3) * 3 + (j % 3);
if (board[r][c] != '.' && cube.find(board[r][c]) != cube.end()) return false;
else cube.insert(board[r][c]);
}
}
return true;
}
};