37.解数独
题目:编写一个程序,通过填充空格来解决数独问题。
一个数独的解法需遵循如下规则:
1.数字 1-9 在每一行只能出现一次。
2.数字 1-9 在每一列只能出现一次。
3.数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。
class Solution {
public:
void solveSudoku(vector<vector<char>>& board) {
//定义二维数组
rows = vector<vector<int>>(9, vector<int>(10));
cols = vector<vector<int>>(9, vector<int>(10));
boxes = vector<vector<int>>(9, vector<int>(10));
//两个for循环遍历整个表
for(int i = 0; i < 9; i++)
{
for(int j = 0; j < 9; j++)
{
//获得当前位置表格的数字
const char c = board[i][j];
if(c != '.')
{
int bx = j / 3;
int by = i / 3;
int n = c - '0';
rows[i][n] = 1;
cols[j][n] = 1;
//3x3格子的标号
boxes[by *3 + bx][n] = 1;
}
}
}
dfs(board, 0, 0);
}
private:
vector<vector<int>> rows, cols, boxes;
bool dfs(vector<vector<char>>& board, int x, int y){
//递归中值条件
if(y == 9)
return true;
//x在循环中不断+1,通过取模获得对应列坐标
int nx = (x+1)%9;
//通过三目运算符判断,当nx为0时,对应行进行累加
int ny = (nx == 0) ? y+1 : y;
//如果当前表格位置有数字(不为空),则进行下一次递归搜索
if(board[y][x] != '.') return dfs(board, nx, ny);
//for循环遍历9个数字
for(int i = 1; i <= 9; i++)
{
int bx = x / 3;
int by = y / 3;
//获得3x3box 的标号
int box_key = by * 3 + bx;
//如果当前数字没有在行、列、和3x3box中出现过,则可以用
if(!rows[y][i] && !cols[x][i] && !boxes[box_key][i])
{
//将当前数字对应的行、列、3x3box标记为1
rows[y][i] = 1;
cols[x][i] = 1;
boxes[box_key][i] = 1;
//将当前数字填入当前表格
board[y][x] = i + '0';
//满足条件则进行下一次递归
if(dfs(board, nx, ny)) return true;
//以下几步为删除之前的标记,一边进行下一次回溯
board[y][x] = '.';
boxes[box_key][i] = 0;
cols[x][i] = 0;
rows[y][i] = 0;
}
}
return false;
}
};