题目
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 ‘.’ 表示。
注意:
给定的数独序列只包含数字 1-9 和字符 ‘.’ 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
解法
本道题类似于八皇后问题,在填充的位置放入1~9 数字,能放入的就继续往下走继续放,如果放的数字导致后面的不能放入就进行回溯。
首先,建立三个 二维数组 用来标记每行每列和每个格子能放入数字的条件,用来判断当前位置能不能放入这个数字
然后进行循环递归
class Solution {
public void solveSudoku(char[][] board) {
//用来判断放入的数字是否符合数独
boolean[][] row = new boolean[9][9];
boolean[][] col = new boolean[9][9];
boolean[][] box = new boolean[9][9];
//填充表格中已经存在的数字
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] != '.') {
int n = board[i][j] - '1';
row[i][n] = true;
col[j][n] = true;
box[i / 3 * 3 + j / 3][n] = true;
}
}
}
dfs(board, row, col, box, 0, 0);
}
private boolean dfs (char[][] board, boolean[][] row, boolean[][] col, boolean[][] box, int i, int j) {
//判断边界条件,达到数独最后位置后返回true
if(j == board[0].length){
j = 0;
i++;
if(i == board.length){
return true;
}
}
//如果当前位置能填充
if (board[i][j] == '.'){
//遍历1-9数字填充
for (int n = 1; n <= 9; n++) {
int boxIndex = i / 3 * 3 + j / 3;
//判断填充的数字是否符合数独条件
if (!row[i][n-1] && !col[j][n-1] && !box[boxIndex][n-1]) {
board[i][j] = (char) ('0' + n);
row[i][n-1] = true;
col[j][n-1] = true;
box[boxIndex][n-1] = true;
//符合条件,则继续往下一个位置填充
if (dfs(board,row,col,box,i,j + 1)) {
return true;
}
//不然的话,就回溯
row[i][n-1] = false;
col[j][n-1] = false;
box[boxIndex][n-1] = false;
board[i][j] = '.';
}
}
} else {//当前位置不是空格,就往下一个位置填充
return dfs(board, row, col, box, i, j + 1);
}
//如果没有达到边界条件,但是已经1-9数字都不能填充进去,就返回false,数独不能填充完成
return false;
}
}