编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
空白格用 '.'
表示。
一个数独。
答案被标成红色。
Note:
- 给定的数独序列只包含数字
1-9
和字符'.'
。 - 你可以假设给定的数独只有唯一解。
- 给定数独永远是
9x9
形式的。
解题思路
使用boolean二维数组来记录行、列、3*3小宫格。
给已经存在的数字记录为true
DFS:遍历完全部的行返回true。
从1开始填充数字
class Solution {
public void solveSudoku(char[][] board) {
//记录某行的,某位数字是否已经摆放
boolean[][] row = new boolean[9][10];
//记录某一列,某位数字是否被摆放
boolean[][] col = new boolean[9][10];
//记录某3*3宫格内,某位数字是否被摆放
boolean[][] block = new boolean[9][10];
//给已经存在的数字记录为true
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] = true;
col[j][num] = true;
block[i / 3 * 3 + j / 3][num] = true;
}
}
}
dfs(board,row,col,block,0,0);//回溯
}
public boolean dfs(char[][] board,boolean[][] row, boolean[][] col,boolean[][] block,int i,int j){
while(board[i][j] != '.'){
if(++j >= 9){//遍历完行的这一列,遍历下一行
i++;
j=0;
}
if(i >= 9){//遍历全部的行,返回true
return true;
}
}
for(int num = 1; num <=9; num++){//num为该数组里面的数字,假设从1开始填充数字
int blockIndex= i / 3 * 3 + j / 3;
if(!row[i][num] && !col[j][num] && !block[blockIndex][num]){//如果当前的数字不被包含在已经存在的数字里,则进行递归
board[i][j] = (char)('0' + num);//把num变成char字符
row[i][num] = true;
col[j][num] = true;
block[blockIndex][num] = true;//表示该数字添加入已经存在数组里
if(dfs(board,row,col,block,i,j)){
return true;
}else{
//回溯
row[i][num] = false;
col[j][num] = false;
block[i / 3 * 3 + j / 3][num] = false;
board[i][j] = '.';
}
}
}
return false;
}
}