思路一:普通回溯法
从左到右,从上到下的遍历顺序遍历二维数组,如果发现单元格内容为'.',则尝试填入1~9,如果填入的值合法,则下探下一个单元格,也尝试填入1~9,如果不合法,则回溯,同时要把下探过的值恢复为'.'
判断填入的值是否合法有三种情况
一、所在的行没有和当前填入的值相同的值出现
二、所在的列没有和当前填入的值相同的值出现
三、所在的子数独中没有和当前填入的值相同的值出现
假设当前尝试填入的单元格为board[row][col];则上面三种情况分别为:i从0到8,
一、没有board[row][i]==c
二、没有board[i][col]==c
三、没有board[3*(row/3)+i/3][3*(col/3)+i%3]==c
根据上面的思路,解法代码如下
public class Test37 {
public void solveSudoku(char[][] board) {
if (board == null || board.length != 9 || board[0] == null || board[0].length != 9) {
return;
}
solve(board);
}
private 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++) {
if(isValid(board, i, j, c)) {
board[i][j] = c;
//如果当前board[i][j]填入c合法,则下探;不合法则回溯,恢复状态
if(solve(board)) {
return true;
} else {
board[i][j] = '.';
}
}
}
return false;
}
}
}
return true;
}
//判断如果board[row][col]的位置填c,数独是否合法
//要判断row所在的行是否有c,col所在的列是否有c,所在的子数独是否有c
private boolean isValid(char[][] board, int row, int col, char c) {
for(int i=0; i<9; i++) {
if(board[row][i]==c
|| board[i][col]==c
|| board[3*(row/3)+i/3][3*(col/3)+i%3]==c) {
return false;
}
}
return true;
}
}