1. 题⽬链接:37.解数独
2. 题⽬描述:
3. 解法:
算法思路: 为了存储每个位置的元素,我们需要定义⼀个⼆维数组。⾸先,我们记录所有已知的数据,然后遍历 所有需要处理的位置,并遍历数字1~9。对于每个位置,我们检查该数字是否可以存放在该位置,同 时检查⾏、列和九宫格是否唯⼀。
我们可以使⽤⼀个⼆维数组来记录每个数字在每⼀⾏中是否出现,⼀个⼆维数组来记录每个数字在每 ⼀列中是否出现。对于九宫格,我们可以以⾏和列除以3得到的商作为九宫格的坐标,并使⽤⼀个三 维数组来记录每个数字在每⼀个九宫格中是否出现。在检查是否存在冲突时,只需检查⾏、列和九宫 格⾥对应的数字是否已被标记。如果数字⾄少有⼀个位置(⾏、列、九宫格)被标记,则存在冲突, 因此不能在该位置放置当前数字。
• 特别地,在本题中,我们需要直接修改给出的数组,因此在找到⼀种可⾏的⽅法时,应该停⽌递 归,以防⽌正确的⽅法被覆盖。
初始化定义:
1. 定义⾏、列、九宫格标记数组以及找到可⾏⽅法的标记变量,将它们初始化为false。
2. 定义⼀个数组来存储每个需要处理的位置。
3. 将题⽬给出的所有元素的⾏、列以及九宫格坐标标记为true。
4. 将所有需要处理的位置存⼊数组。
递归函数设计:void dfs(vector>& board, int pos)
参数:pos(当前需要处理的坐标);
返回值:⽆;
函数作⽤:在当前坐标填⼊合适数字,查找数独答案。
递归流程如下:
1. 结束条件:已经处理完所有需要处理的元素。如果找到了可⾏的解决⽅案,则将标记变量更新为 true并返回。
2. 获取当前需要处理的元素的⾏列值。
3. 遍历数字1~9。如果当前数字可以填⼊当前位置,并且标记变量未被赋值为true,则将当前位置的 ⾏、列以及九宫格坐标标记为true,将当前数字赋值给board数组中的相应位置元素,然后对下⼀ 个位置进⾏递归。
4. 递归结束时,撤回标记。
C++算法代码:
class Solution
{
public:
//行、列、组状态数组
bool hang[9][10], lie[9][10], zu[3][3][10];
bool dfs(vector<vector<char>>& board, int h, int l)
{
//填数
for (int i = h; i < 9; i++)
{
for (int j = l; j < 9; j++)
{
if (board[i][j] == '.')
{
for (int k = 1; k < 10; k++)
{
if (!hang[i][k] && !lie[j][k] && !zu[i/3][j/3][k])
{
hang[i][k] = true;
lie[j][k] = true;
zu[i/3][j/3][k] = true;
board[i][j] = k + '0';
//如果之后的递归找到合适的数,则返回ture
if(dfs(board, i, j)==true)
{
return true;
}
hang[i][k] = false;
lie[j][k] = false;
zu[i/3][j/3][k] = false;
board[i][j] = '.';
}
}
//没找到返回false,尝试下一个数
return false;
}
}
}
//所有空填完了返回true
return true;
}
void solveSudoku(vector<vector<char>>& board)
{
//状态数组初始化
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
hang[i][board[i][j] - '0'] = true;
lie[j][board[i][j] - '0'] = true;
zu[i / 3][j / 3][board[i][j] - '0'] = true;
}
}
dfs(board, 0, 0);
}
};
Java算法代码:
class Solution
{
boolean[][] row, col;
boolean[][][] grid;
public void solveSudoku(char[][] board)
{
row = new boolean[9][10];
col = new boolean[9][10];
grid = new boolean[3][3][10];
// 初始化
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
if (board[i][j] != '.')
{
int num = board[i][j] - '0';
row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = true;
}
dfs(board);
}
public boolean dfs(char[][] board)
{
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 9; j++)
{
if (board[i][j] == '.')
{
// 填数
for (int num = 1; num <= 9; num++)
{
// 剪枝
if (!row[i][num] && !col[j][num] && !grid[i / 3][j / 3][num])
{
board[i][j] = (char)('0' + num);
row[i][num] = col[j][num] = grid[i / 3][j / 3]
[num] = true;
if (dfs(board) == true) return true; // 重点理解
// 恢复现场
board[i][j] = '.';
row[i][num] = col[j][num] = grid[i / 3][j / 3]
[num] = false;
}
}
return false; // 重点理解
}
}
}
return true; // 重点理解
}
}