题目:
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
- 数字
1-9
在每一行只能出现一次。 - 数字
1-9
在每一列只能出现一次。 - 数字
1-9
在每一个以粗实线分隔的3x3
宫内只能出现一次。
空白格用 '.'
表示。
一个数独。
答案被标成红色。
Note:
- 给定的数独序列只包含数字
1-9
和字符'.'
。 - 你可以假设给定的数独只有唯一解。
- 给定数独永远是
9x9
形式的。
解答:
class Solution {
public void solveSudoku(char[][] board) {
//特殊情况直接返回
if(board == null || board.length != 9 || board[0].length != 9) return;
solve(board);
}
public boolean solve(char[][] board){
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
//先找到需要填充字的位置
if(board[i][j] == '.'){
//找到需要填充的位置之后,从1-9依次尝试是否可填
for(char c = '1'; c <= '9'; c++){
//判断[i][j]位置填上字符c是否能满足数独的定义
if(isValid(board, i, j, c)){
//如果[i][j]位置填上字符c后经过判断,满足数独定义,就把[i][j]置为c
board[i][j] = c;
//调用递归函数,DFS,判断[i][j]位置填上字符c后是否存在有效解
if(solve(board)){
return true;
}else{ //否则回溯,返回上一层
board[i][j] = '.';
}
}
}
//1-9试过之后如果都不行的话,返回false
return false;
}
}
}
return true;
}
//此函数用于判断[i][j]位置填上字符c后是否满足数独的定义
public boolean isValid(char[][] board, int row, int col, char c){
//判断第row行和第col列是否已经存在c字符,若存在则不满足数独定义,返回false
for(int i = 0; i < 9; i++){
if(board[i][col] != '.' && board[i][col] == c) return false;
if(board[row][i] != '.' && board[row][i] == c) return false;
}
//下面是不好理解的部分
//下面用于判断[row][col]所在的3 * 3小矩阵内是否已经存在过c字符
int rowoff = (row / 3) * 3;
int coloff = (col / 3) * 3;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(board[rowoff + i][coloff + j] != '.' && board[rowoff + i][coloff + j] == c) return false;
}
}
//如果判断都通过了,返回true
return true;
}
}