【LeetCode每日一题】37.解数独
37.解数独
题目来源link
算法思想:回溯法,递归;
java代码
class Solution {
private boolean[][] line = new boolean[9][9];//用于存储第i行,是否有数字j
private boolean[][] column = new boolean[9][9];//用于存储第i列,是否有数字j
private boolean[][][] block = new boolean[3][3][9];//用于存储第[i][j]块,是否有数字k
private boolean vaild = false;//正确答案之后的回溯条件;
private List<int[]> space = new ArrayList<>();//用于存储数独中空位置的坐标
//初始化line,column,block数组
public void solveSudoku(char[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board.length; j++) {
if (board[i][j] == '.') {
space.add(new int[]{
i,j});
}
else {
//记录数独中已经存在的数字
int dight = board[i][j]-'0';//数独[i][j]中的数字
line[i][dight-1] = true;
column[j][dight-1] = true;
block[i/3][j/3][dight-1] = true;
}
}
}
//开始尝试填写数独
dfs(board,0);
}
public void dfs(char[][] board, int numSpace) {
if (numSpace == space.size()) {
//所有空格填写完成,即找到答案,则返回
vaild = true;
return;
}//回溯条件:
int[] temp = space.get(numSpace);//获取空位置[i][j]
int i = temp[0];
int j = temp[1];
//回溯关键条件vaild,这里一定要判断!vaild
//找打一个答案之后,将vaild设置成true,进行回溯
for (int num = 0; num < 9 && !vaild; num++) {
//判断当前空位置的行,列,块;能否填入num数字
if (!line[i][num] && !column[j][num] && !block[i/3][j/3][num]) {
//尝试填入num;将num相关行,列,块,设置成true
line[i][num] = true;
column[j][num] = true;
block[i/3][j/3][num] = true;
board[i][j] = (char) ('1' + num);//填入数字num;
dfs(board, numSpace+1);//向下尝试,尝试下一个空位置;
//dfs返回后包含两种情形:
//1.已经找到了答案,此时vaild=true;不再进行for循环;继续回溯;
//2.没有找到了答案,此时vaild=false;再进行for循环;继续尝试;
line[i][num] = false;
column[j][num] = false;
block[i/3][j/3][num] = false;
//无论以上何种情形,都将进行行,列,块的设置false;所以最后line,column,block数组没有变化
}
}
}
}