题目:
Write a program to solve a Sudoku puzzle by filling the empty cells.
Empty cells are indicated by the character '.'
.
You may assume that there will be only one unique solution.
A sudoku puzzle...
...and its solution numbers marked in red.
解法:看到这种方格子填数字的问题我第一时间就想到了8皇后问题,基本解法就是回溯法,在第一个为“。”符号的位置尝试一种可能的数字,再判断此时数独是否合法:如果合法,就递归求解子问题(如果子问题解决返回true,则返回true,如果子问题解决返回false,则在当前位置尝试下一个可能值),如果不合法则尝试下一种可能,如果所有都不合法则return false,回溯到上一节点。
值得注意的是,上面用到的判断数独是否合法的算法,并不需要用到上一题的方法,因为这一题已经保证了初始的输入是合法的,于是只需判断新加入的元素的那一行,那一列,以及那一个子栅格是否合法即可,连HashSet都不需要用到。
public class No36_SudokuSolver {
public static void main(String[] args){
}
public static void solveSudoku(char[][] board) {
solveSudokuWithLogic(board);
}
public static boolean solveSudokuWithLogic(char[][] board){
int i = 0;
int j = 0;
for(;i<board.length;i++){
j = 0;
for(;j<board[0].length;j++){
if(board[i][j] == '.')
break;
}
if(j != board[0].length)
break;
}
if(i == board.length) return true;
char k = '1';
while(k-'0'<=9){
board[i][j] = k;
if(isValid(board, i, j)){
boolean isSuccess = solveSudokuWithLogic(board);
if(isSuccess) return true;
}
k++;
continue;
}
board[i][j] = '.';
return false;
}
public static boolean isValid(char[][] board, int x, int y){
int row = x;
int column = 0;
for(;column<board[0].length;column++){
if(column == y) continue;
if(board[row][column] == board[row][y]) return false;
}
column = y;
row = 0;
for(;row<board.length;row++){
if(row == x) continue;
if(board[row][column] == board[x][column]) return false;
}
row = x/3*3;
column = y/3*3;
for(int p=row;p<row+3;p++){
for(int q=column;q<column+3;q++){
if(p==x && q==y) continue;
if(board[p][q] == board[x][y]) return false;
}
}
return true;
}
}