难度:困难。
标签:回溯法。
具体判断条件与上一题的相同,可见【36. 有效的数独】
开始写的一直有问题,原因:
- 在每次回溯结束时,没有将数据重置,即缺失 30-35行的代码。
- solve没有返回bool值,由此没有办法完成剪枝的操作。
- 4-11行的代码有问题,开始是这样写的:
if(board[i][j] != '.'){
if(j < 8){
solve(board, i, j + 1, flags);
}
else if(i < 8){
solve(board, i + 1, 0, flags);
}
else{
return true;
}
}
根本原因是对回溯法还不够熟悉,思路有点问题。
正确解法:
class Solution {
bool solve(vector<vector<char>>& board, int i, int j, int flags[][10]){
while(board[i][j] != '.'){
if(j < 9)j++;
else if(i < 8){
i++;
j = 0;
}
else return true;
}
int k1 = i , k2 = 9 + j, k3 = 18 + (i / 3) * 3 + (j / 3);
for(int num = 1; num < 10; num++){
if(flags[k1][num] == 0 && flags[k2][num] == 0 && flags[k3][num] == 0){
board[i][j] = '0' + num;
flags[k1][num] = 1;
flags[k2][num] = 1;
flags[k3][num] = 1;
int new_i = i, new_j = j;
if(j < 8) new_j = j + 1;
else if(i < 8){
new_i = i + 1;
new_j = 0;
}
else return true;
if(solve(board, new_i, new_j, flags)){
return true;
}else{
board[i][j] = '.';
flags[k1][num] = 0;
flags[k2][num] = 0;
flags[k3][num] = 0;
}
}
}
return false;
}
public:
void solveSudoku(vector<vector<char>>& board) {
int flags[27][10] = {0};
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
if(board[i][j] == '.')continue;
int num = board[i][j] - '0';
int k1 = i , k2 = 9 + j, k3 = 18 + (i / 3) * 3 + (j / 3);
flags[k1][num] = 1;
flags[k2][num] = 1;
flags[k3][num] = 1;
}
}
solve(board, 0, 0, flags);
}
};
结果: