37. 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.
LeetCode-36. Valid Sudoku (JAVA)(有效数独)
N皇后问题。就是一点点尝试着填数,不行的话就回溯,直到都填满就返回。
如果对一个格子尝试从0~9都不行,那么说明整个sudoku无解,返回false就好。
对整个棋盘所有'.'都填完了,那么就可以返回true了。LeetCode-51. N-Queens (JAVA)(打印N皇后解集)
LeetCode-52. N-Queens II (JAVA)(N皇后解集个数)
public void solveSudoku(char[][] board) {
if (board == null || board.length == 0)
return;
dfs(board);
}
// 也是按照行进行放置,只不过n后问题每行只放一个Q,不重复放置,是一层循环
// 而此题需要放置多个数字,还不能重复,所以是一个三层循环
private boolean dfs(char[][] board) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] == '.') {
for (char num = '1'; num <= '9'; num++) {
// 尝试
if (validate(board, i, j, num)) {
board[i][j] = num;
if (dfs(board))
return true;
else// 回溯
board[i][j] = '.';
}
}
// 如果对一个格子尝试从0~9都不行,
// 那么说明整个sudoku无解,返回false
return false;
}
}
}
// 对整个棋盘所有'.'都填完了,那么就可以返回true了。
return true;
}
// 通常验证函数需要单独解耦合
private boolean validate(char[][] board,
int i, int j, char c) {
// check column(列)
for (int row = 0; row < 9; row++)
if (board[row][j] == c)
return false;
// check row(行)
for (int col = 0; col < 9; col++)
if (board[i][col] == c)
return false;
// check cube(小九宫格)
int rIdx = i / 3 * 3;
int cIdx = j / 3 * 3;
for (int row = rIdx; row < rIdx + 3; row++)
for (int col = cIdx; col < cIdx + 3; col++)
if (board[row][col] == c)
return false;
return true;
}
discuss 解法,简介
public void solveSudoku(char[][] board) {
dfs(board, 0);
}
// 思想是如果是数字直接进入下一层递归
// 如果是.就填入并且验证合法性,验证通过进入下一层递归
private boolean dfs(char[][] board, int d) {
if (d == 81)
return true;
int i = d / 9, j = d % 9;
// found solution(寻找解集)
// 如果是数字,进入下一层递归
if (board[i][j] != '.')
// prefill number skip
// 预填数字
return dfs(board, d + 1);
// 如果不是数字,填入数字并且验证
boolean[] flag = new boolean[10];
validate(board, i, j, flag);
for (int k = 1; k <= 9; k++) {
// flag[k]为true,说明此数字可用
if (flag[k]) {
// 填入
board[i][j] = (char) ('0' + k);
// 验证通过进入下一层递归
if (dfs(board, d + 1))
// 如果下一层验证通过返回true
return true;
}
}
// if can not solve, in the wrong path, change
// back to '.' and out
board[i][j] = '.';
return false;
}
private void validate(char[][] board, int i, int j, boolean[] flag) {
Arrays.fill(flag, true);
for (int k = 0; k < 9; k++) {
if (board[i][k] != '.')
flag[board[i][k] - '0'] = false;
if (board[k][j] != '.')
flag[board[k][j] - '0'] = false;
int r = i / 3 * 3 + k / 3;
int c = j / 3 * 3 + k % 3;
if (board[r][c] != '.')
flag[board[r][c] - '0'] = false;
}
}
Reference:http://rleetcode.blogspot.com/2014/01/sudoku-solver-java.html