问题描述
![这里写图片描述](https://i-blog.csdnimg.cn/blog_migrate/dd8ff754b61ea535e9f8b7bf304779f6.png)
问题分析
- 该题是 LeetCode 36. Valid Sudoku 的进阶, 36是验证一个二维矩阵是否合法,而该题是根据三条规则填好这个二维矩阵。
- 该题有点类似于 N 皇后问题,N皇后问题是逐行放置皇后,使皇后放置的位置满足同一行,同一列,以及对角戏原则,一行放好去放下一行。最终返回所有的可能性解,便是用DFS + 回溯。函数返回值为 void。
而该题是从左到右,从上到下,逐个空格去填数,遇到有数字的情况去填下一个空格,对于每个空格,尝试去填 1 ~ 9 任意一个数字,看是否满足那三条规则,若满足,则继续DFS去填下一个空格,若不满足, 则尝试 1 ~ 9中另一个数字。若选中了一个数字当前满足,以后不满足了,需要再回溯到这一步,选择另一个数字。若 1 ~ 9 都不满足,则返回false ,说明以前的步骤填错了,需要回溯回去。
因为该题是填表,并且只有一个解,所以需要将函数返回类型设为 boolean,一旦后序都能填好,便直接return,不再回溯去填其他数字。
经验教训
- 对比该题和 N皇后的题目,如何根据题目要求去设计dfs函数参数以及返回值。
代码实现
class Solution {
public void solveSudoku(char[][] board) {
if (board == null || board.length == 0 || board[0] == null || board[0].length == 0) {
return;
}
dfs(board, 0, 0);
}
public boolean dfs(char[][] board, int x ,int y) {
if (x == 9) {
return true;
}
int nextY = y + 1 == 9 ? 0 : y + 1;
int nextX = y + 1 == 9 ? x + 1 : x;
if (board[x][y] == '.') {
for (char ch = '1'; ch <= '9'; ++ch) {
if (isVaildSudoku(board, ch, x, y)) {
board[x][y] = ch;
if (dfs(board, nextX, nextY)) {
return true;
}
board[x][y] = '.';
}
}
return false;
}else {
return dfs(board, nextX, nextY);
}
}
public boolean isVaildSudoku(char[][] board, char ch, int row, int col) {
for (int i = 0; i < 9; ++i) {
if (board[i][col] == ch || board[row][i] == ch || board[3 * (row / 3) + i / 3][3 * (col / 3) + i % 3] == ch) {
return false;
}
}
return true;
}
}