题目:
编写一个程序,通过填充空格来解决数独问题。
数独的解法需 遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 '.'
表示。
思路:
第一步:确定参数与返回值。参数为二维数组board,代表数独局势。返回值为布尔类型,找到一个符合的条件(就在树的叶子节点上)立刻就返回。
第二步:确定终止条件。本题递归不用终止条件,解数独是要遍历整个树形结构寻找可能的叶子节点就立刻返回。
第三步:确定单层递归逻辑。一个for循环遍历棋盘的行,一个for循环遍历棋盘的列,一行一列确定下来之后,递归遍历这个位置放9个数字的可能性。
代码:
public void solveSudoku(char[][] board) {
backTracking(board);
}
public boolean backTracking(char[][] board){
for(int i=0;i<9;i++){//遍历行
for(int j=0;j<9;j++){//遍历列
if(board[i][j]!='.')//已有数字,跳过
continue;
for(char k='1';k<='9';k++){
if(isValid(i,j,k,board)){
board[i][j]=k;//处理
if(backTracking(board))//递归,找到一组合法的解,结束
return true;
board[i][j]='.';//回溯
}
}
return false;//1-9都不合法,无解
}
}
return true;
}
//判断数独是否合法,(row,col)为val值的局面坐标,board为数独局势
public boolean isValid(int row,int col,char val,char[][] board){
//条件一:同行不重复
for(int i=0;i<9;i++){
if(board[row][i]==val)
return false;
}
//条件二:同列不重复
for(int j=0;j<9;j++){
if(board[j][col]==val)
return false;
}
//条件三:九宫格内不重复
int startRow=(row/3)*3;
int startCol=(col/3)*3;
for(int i=startRow;i<startRow+3;i++){
for(int j=startCol;j<startCol+3;j++){
if(board[i][j]==val)
return false;
}
}
return true;
}