Sudoku solver

basic frame

``````void solveSudoku(char[][] board) {
backtrack(board, 0, 0);
}

void backtrack(char[][] board, int r, int c) {
int m = 9, n = 9;
// 就是对棋盘的每个位置进行穷举
for (int i = r; i < m; i++) {
for (int j = c; j < n; j++) {
// make a move
backtrack(board, i, j);
// undo
}
}
}
``````

what move:

``````void backtrack(char[][] board, int r, int c) {
int m = 9, n = 9;
// 就是对每个位置进行穷举
for (int i = r; i < m; i++) {
for (int j = c; j < n; j++) {
for (char ch = '1'; ch <= '9'; ch++) {
board[i][j] = ch; // make a move
// 继续穷举下一个
backtrack(board, i, j + 1);
board[i][j] = '.'; // undo
}
}
}
}
``````
• 在穷举之前添加一个判断，跳过不满足条件的数字
• `j`到达超过最后一个索引时，转为增加`i`开始穷举下一行
``````void backtrack(char[][] board, int r, int c) {
int m = 9, n = 9;
if (c == n) {
// 穷举到最后一列的话就换到下一行重新开始。
backtrack(board, r + 1, 0);
return;
}
// 就是对每个位置进行穷举
for (int i = r; i < m; i++) {
for (int j = c; j < n; j++) {
// 如果该位置是预设的数字，不用我们操心
if (board[i][j] != '.') {
backtrack(board, i, j + 1);
return;
}

for (char ch = '1'; ch <= '9'; ch++) {
// 如果遇到不合法的数字，就跳过
if (!isValid(board, i, j, ch))
continue;

board[i][j] = ch;
backtrack(board, i, j + 1);
board[i][j] = '.';
}
}
}
}

// 判断 board[i][j] 是否可以填入 n
boolean isValid(char[][] board, int r, int c, char n) {
for (int i = 0; i < 9; i++) {
// 判断行是否存在重复
if (board[r][i] == n) return false;
// 判断列是否存在重复
if (board[i][c] == n) return false;
// 判断 3 x 3 方框是否存在重复
if (board[(r/3)*3 + i/3][(c/3)*3 + i%3] == n)
return false;
}
return true;
}
``````
• base case: `r == m`
• `backtrack`: return `boolean`: 如果找到一个可行解就返回 true，阻止后续的递归, 减少复杂度
``````boolean backtrack(char[][] board, int r, int c) {
int m = 9, n = 9;
if (c == n) {
// 穷举到最后一列的话就换到下一行重新开始。
return backtrack(board, r + 1, 0);
}
if (r == m) {
// 找到一个可行解，触发 base case
return true;
}
// 就是对每个位置进行穷举
for (int i = r; i < m; i++) {
for (int j = c; j < n; j++) {

if (board[i][j] != '.') {
// 如果有预设数字，不用我们穷举
return backtrack(board, i, j + 1);
}

for (char ch = '1'; ch <= '9'; ch++) {
// 如果遇到不合法的数字，就跳过
if (!isValid(board, i, j, ch))
continue;

board[i][j] = ch;
// 如果找到一个可行解，立即结束
if (backtrack(board, i, j + 1)) {
return true;
}
board[i][j] = '.';
}
// 穷举完 1~9，依然没有找到可行解，此路不通
return false;
}
}
return false;
}

boolean isValid(char[][] board, int r, int c, char n) {
// previous
}
``````