题目描述(困难难度)
算法
(DFS) $O((9!)^9)$
- 枚举每个点,如果是空格,就选择合适的点进行填数,然后不断往下搜索,直到填完所有数(x == n)时,dfs从里不断返回true,直到退到最外面的递归函数位置
- 这里bool型dfs的好处是可以防止找到一种方案了,还去恢复现场
- 注意:这里不同于n皇后问题,这里是修改原数组(修改成一种可行解即可),而皇后问题是输出结果,不是修改原数组
时间复杂度是$O((9!)^9)$:
- 第一行的格子最多有9!种可能
- 第二行的格子最多有87..1=8!种可能
- 第三行的格子最多有76..1=7!种可能
所以不管怎么样,最多也就$(9!)^9$次操作
C++代码
class Solution {
public:
// row[x][u]表示第x行是否已经填过数字u(0-8)
// col[y][u]表示第y行是否已经填过数字u(0-8)
// box[x / 3][y / 3][u]表示第[x/3,y/3]个box是否已经填过数字u(0-8)
bool row[9][9] = {0}, col[9][9] = {0}, cell[3][3][9] = {0};
void solveSudoku(vector<vector<char>>& board) {
for (int i = 0; i < 9; i ++ ) {
for (int j = 0; j < 9; j ++ ) {
char c = board[i][j];
if (c != '.') {
int u = c - '1'; // u: '1' - '1' = 0
row[i][u] = col[j][u] = cell[i / 3][j / 3][u] = true;
}
}
}
dfs(board, 0, 0);
}
bool dfs(vector<vector<char>>& board, int x, int y) {
if (y == 9) x ++ , y = 0; // 先改变
if (x == 9) return true; // 填完所有格子,返回true
if (board[x][y] != '.') return dfs(board, x, y + 1);
for (int i = 0; i < 9; i ++ ) {
if (!row[x][i] && !col[y][i] && !cell[x / 3][y / 3][i]) {
board[x][y] = i + '1';
row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = true;
// 如果下面搜索后是对的,就提前返回,不恢复现场(因为要修改board);
// 如果是false就恢复现场(这个方法很巧妙)
if (dfs(board, x, y + 1)) return true;
board[x][y] = '.';
row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = 0;
}
}
return false;
}
};
未用bool型dfs会显得很麻烦,效率低下
440 ms 91.4 MB
class Solution {
public:
bool col[9][10], row[9][10], box[3][3][10];
int n, m;
void dfs(int x, int y, vector<vector<char>> tmp, vector<vector<char>> & board) {
if (y == 9) x ++, y = 0;
if (x == 9) { // 皇后问题是在这输出结果
for (int i = 0; i < n; i ++) {
for (int j = 0; j < m; j ++) {
board[i][j] = tmp[i][j];
}
}
return;
}
if (tmp[x][y] != '.') dfs(x , y + 1, tmp, board);
else { // 填数
for (int i = 1; i <= 9; i ++) {
if (!col[x][i] && !row[y][i] && !box[x / 3][y / 3][i]) {
tmp[x][y] = i + '0';
col[x][i] = row[y][i] = box[x / 3][y / 3][i] = true;
dfs(x, y + 1,tmp, board);
col[x][i] = row[y][i] = box[x / 3][y / 3][i] = false; // 恢复现场
tmp[x][y] = '.';
}
}
}
return;
}
void solveSudoku(vector<vector<char>>& board) {
n = board.size(), m = board[0].size();
for (int x = 0; x < n; x ++) {
for (int y = 0; y < m; y ++) {
if (board[x][y] != '.') {
int i = board[x][y] - '0'; // i:1-9
col[x][i] = row[y][i] = box[x / 3][y / 3][i] = true;
}
}
}
dfs(0, 0, board, board);
return;
}
};
为什么底下的是-‘0’不是‘1’
懂了,之前也一直在疑惑为什么要返回bool。看到你的解答很有帮助
感谢支持!