题目:Sudoku Solver
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.
分析:根据数独的规则,这道题用深度优先遍历是最自然的。
要点:
- 建立辅助变量用于快速判断一个数字是否在当前行,列和区间已经被使用了。
- 要有二维数组转一维数组以及数组映射的思想。
- 给出一个数字,如第56个格子(从左往右,从上往下),怎么计算出它的坐标在哪呢?
row = 56 / 9, column = 56 % 9
- 如一个数独游戏有九个独立的九宫格,那我们该怎么判断一个坐标(i,j)是否在某个九宫格里呢?
- 给出一个数字,如第56个格子(从左往右,从上往下),怎么计算出它的坐标在哪呢?
- 深度优先的递归函数最好只有一个迭代的参数,否则很容易给自己挖坑。如我只传给solve函数一个pos变量,告诉它我要处理第pos个格子。而不是传入(i, j)表示坐标。
代码:
public class Solution {
public void solveSudoku(char[][] board) {
rowUsed = new boolean[10][10];
columnUsed = new boolean[10][10];
blockUsed = new boolean[3][3][10];
int num;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') continue;
num = board[i][j] - '0';
rowUsed[i][num] = true;
columnUsed[j][num] = true;
blockUsed[i/3][j/3][num] = true;
}
}
solve(board, 0);
}
private boolean solve(char[][] board, int pos) {
int row = pos / 9;
int column = pos % 9;
// looks we have already finish the board
if (pos > 80) return true;
if (board[row][column] != '.') {
return solve(board, pos+1);
}
for (int num = 1; num < 10; num++) {
if (rowUsed[row][num] || columnUsed[column][num] || blockUsed[row/3][column/3][num]) continue;
rowUsed[row][num] = columnUsed[column][num] = blockUsed[row/3][column/3][num] = true;
board[row][column] = (char)('0' + num);
if (solve(board, pos + 1)) {
return true;//if get the valid solution, don't go further
} else {
board[row][column] = '.';
rowUsed[row][num] = columnUsed[column][num] = blockUsed[row/3][column/3][num] = false;
}
}
return false;
}
private boolean[][] rowUsed;
private boolean[][] columnUsed;
private boolean[][][] blockUsed;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。