相当于进阶:LeetCode第 36 题:有效的数独(C++)_zj-CSDN博客
dfs枚举:
class Solution {
public:
int row[9][9], col[9][9], block[9][9];
void solveSudoku(vector<vector<char>>& board) {
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';
row[i][num] = col[j][num] = block[i/3*3 + j/3][num] = 1;
}
}
dfs(board, 0, 0);
}
bool dfs(vector<vector<char>>& board, int r, int c){
if(r > 8) return true;
if(board[r][c] == '.'){
for(int i = 0; i < 9; ++i){//枚举可以填入的数字
if(row[r][i] || col[c][i] || block[r/3*3 + c/3][i]) continue;//不符合要求,该数字已存在
board[r][c] = i+1+'0';
row[r][i] = col[c][i] = block[r/3*3 + c/3][i] = 1;
if(c != 8){//先增加列
if(dfs(board, r, c+1)) return true;
}else{//一列结束再增加行
if(dfs(board, r+1, 0)) return true;
}
board[r][c] = '.';//撤销选择
row[r][i] = col[c][i] = block[r/3*3 + c/3][i] = 0;
}
}
else{
if(c != 8){//先增加列
if(dfs(board, r, c+1)) return true;
}else{//一列结束再增加行
if(dfs(board, r+1, 0)) return true;
}
}
return false;//无解
}
};
优化以下行列判断:
class Solution {
public:
int row[9][9], col[9][9], block[9][9];
void solveSudoku(vector<vector<char>>& board) {
for(int i = 0; i < 9; ++i){//初始化行列以及block,方便后续查询
for(int j = 0; j < 9; ++j){
if(board[i][j] == '.') continue;
int num = board[i][j] - '1';
row[i][num] = col[j][num] = block[i/3*3 + j/3][num] = 1;
}
}
dfs(board, 0, 0);
}
bool dfs(vector<vector<char>>& board, int r, int c){
if(r > 8) return true;
if(board[r][c] == '.'){
for(int i = 0; i < 9; ++i){//枚举可以填入的数字
if(row[r][i] || col[c][i] || block[r/3*3 + c/3][i]) continue;//不符合要求,该数字已存在
board[r][c] = i+1+'0';
row[r][i] = col[c][i] = block[r/3*3 + c/3][i] = 1;
//先判断第一行的9列,然后再判断第二行的9列,一直到最后一行,即r>8
//r+(c+1)/9, (c+1)%9的使用非常巧妙
if(dfs(board, r+(c+1)/9, (c+1)%9)) return true;
board[r][c] = '.';
row[r][i] = col[c][i] = block[r/3*3 + c/3][i] = 0;
}
}
else return dfs(board, r+(c+1)/9, (c+1)%9);
return false;//无解
}
};