1. 题目来源
链接:37. 解数独
2. 题目解析
暴搜。
开三个判重的 bool
数组,分别对行、列、九宫格检查是否有重复元素。注意普通的下标与九宫格之间的映射关系,二维数组遍历下标行列均是从 0 到 8,其中 0~2、3~5、6~8
是三个九宫格的起点位置,则 i/3、j/3
就能将下标 i、j
映射到九宫格中,以便以重复元素判断。
思路:
- 按行暴搜,枚举每一格的
1~9
的所有情况,若该位置本来有数字,即bool
数组为true
的情况下,则跳过该空格,令y ++
即可 - 当
y == 9
,即y
到达了边界位置,则进行下一行的首元素判断,令x ++,y = 0
,若x == 9
,则数独遍历完毕,找到了唯一解,返回true
即可 - 注意回溯的时候恢复现场即可
填充数独的时间复杂度是很恐怖的,当然优化的方案也是很多,本题 dfs
是最为暴力的解法了。
时间复杂度:不会分析…
空间复杂度:不会分析…
代码:
class Solution {
public:
bool row[9][9], col[9][9], cell[3][3][9];
void solveSudoku(vector<vector<char>>& board) {
memset(row, 0, sizeof row);
memset(col, 0, sizeof col);
memset(cell, 0, sizeof cell);
for (int i = 0; i < 9; i ++ ) { // 二维数独元素首先判重
for (int j = 0; j < 9; j ++ ) {
if (board[i][j] != '.') {
int t = board[i][j] - '1';
row[i][t] = col[j][t] = cell[i / 3][j / 3][t] = 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;
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] = (char)(i + '1');
row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = true;
if (dfs(board, x, y + 1)) return true;
board[x][y] = '.';
row[x][i] = col[y][i] = cell[x / 3][y / 3][i] = false;
}
}
return false;
}
};