解法都在代码里,不懂就留言或者私信,比第一题稍微难点
public static void solveSudoku(char[][] board) {
/**定义三个二维数组分别代表行、列、桶(每9个格子)*/
boolean[][] rowExists = new boolean[9][10];
boolean[][] colExists = new boolean[9][10];
boolean[][] bucketExists = new boolean[9][10];
/**根据原始board初始化三个是否存在的二维数组*/
initArrays(board, rowExists, colExists, bucketExists);
process(board, rowExists, colExists, bucketExists, 0, 0);
}
private static boolean process(char[][] board, boolean[][] rowExists, boolean[][] colExists, boolean[][] bucketExists, int curRow, int curCol) {
/**我们是按照行从下到上填的,一行填完才填下一行,如果行越界了,说明正常范围内的行都填完了*/
if(curRow == 9) {
return true;
}
/**如果当前的位置可以填,那下个位置填啥,nextRow和nextCol表示下个要填的位置的行和列*/
int nextRow = curCol == 8? curRow + 1 : curRow;
int nextCol = curCol == 8? 0 : curCol + 1;
/**当前位置填过了就继续填下一个*/
if(board[curRow][curCol] != '.') {
return process(board, rowExists, colExists, bucketExists, nextRow, nextCol);
} else {
/**当前位置可以填就填,那我们填哪些呢?所有的目前符合的(行列桶都不违规)都可以试试*/
for(char c = '1'; c <= '9'; c++) {
int num = c - '0';
int bucketNum = (curRow/3) * 3 + curCol / 3;
/**行、列、桶任意一个存在就不能填*/
if(rowExists[curRow][num] || colExists[curCol][num] || bucketExists[bucketNum][num]) {
continue;
}
board[curRow][curCol] = c;
/**填完之后行、列、桶做标记*/
rowExists[curRow][num] = true;
colExists[curCol][num] = true;
bucketExists[bucketNum][num] = true;
/**如果后面的过程尝试正确就直接返回,否则不处理*/
if(process(board, rowExists, colExists, bucketExists, nextRow, nextCol)) {
return true;
}
/**不成功一定要恢复现场*/
board[curRow][curCol] = '.';
rowExists[curRow][num] = false;
colExists[curCol][num] = false;
bucketExists[bucketNum][num] = false;
}
}
/**如果中间过程都没有返回,返回false*/
return false;
}
/**遍历board初始化是否存在的数组*/
private static void initArrays(char[][] board, boolean[][] rowExists, boolean[][] colExists, boolean[][] bucketExists) {
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[i].length; j++) {
if(board[i][j] == '.') {
continue;
}
int num = board[i][j] - '0';
int bucketNum = (i / 3) * 3 + j / 3;
rowExists[i][num] = true;
colExists[j][num] = true;
bucketExists[bucketNum][num] = true;
}
}
}
运行结果: