原题网址:https://leetcode.com/problems/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.
方法一:深度优先搜索。
public class Solution {
private boolean[][] rows, cols;
private boolean[][][] subs;
private boolean find(char[][] board, int cell) {
if (cell == 81) return true;
int row = cell / 9;
int col = cell % 9;
int subr = row / 3;
int subc = col / 3;
if (board[row][col] != '.') return find(board, cell+1);
for(int i=0; i<9; i++) {
if (rows[row][i] || cols[col][i] || subs[subr][subc][i]) continue;
rows[row][i] = true;
cols[col][i] = true;
subs[subr][subc][i] = true;
board[row][col] = (char)('1' + i);
if (find(board, cell+1)) return true;
rows[row][i] = false;
cols[col][i] = false;
subs[subr][subc][i] = false;
}
board[row][col] = '.';
return false;
}
public void solveSudoku(char[][] board) {
rows = new boolean[9][9];
cols = new boolean[9][9];
subs = new boolean[3][3][9];
for(int row = 0; row < 9; row ++) {
for(int col = 0; col < 9; col ++) {
if (board[row][col] == '.') continue;
int num = board[row][col]-'1';
rows[row][num] = true;
cols[col][num] = true;
int subr = row / 3;
int subc = col / 3;
subs[subr][subc][num] = true;
}
}
find(board, 0);
}
}
方法二:优先处理确定性高的格子,即剪枝,但比较繁琐。
public class Solution {
private Cell[] cells;
private int maxDepth = 0;
private int[] rowSolved, colSolved;
private int[][] subSolved;
private boolean[][] rows, cols;
private boolean[][][] subs;
private boolean find(char[][] board, int depth) {
if (depth == cells.length) return true;
if (depth == maxDepth+1) {
int priority = depth;
for(int i=depth+1; i<cells.length; i++) {
if (cells[i].uncertainty < cells[priority].uncertainty) priority = i;
}
Cell temp = cells[depth];
cells[depth] = cells[priority];
cells[priority] = temp;
maxDepth = depth;
}
int row = cells[depth].row;
int col = cells[depth].col;
int subr = row / 3;
int subc = col / 3;
for(int i=0; i<9; i++) {
if (rows[row][i] || cols[col][i] || subs[subr][subc][i]) continue;
rows[row][i] = true;
cols[col][i] = true;
subs[subr][subc][i] = true;
board[row][col] = (char)('1' + i);
rowSolved[row] ++;
colSolved[col] ++;
subSolved[subr][subc] ++;
if (find(board, depth+1)) return true;
rows[row][i] = false;
cols[col][i] = false;
subs[subr][subc][i] = false;
rowSolved[row] --;
colSolved[col] --;
subSolved[subr][subc] --;
}
board[row][col] = '.';
return false;
}
public void solveSudoku(char[][] board) {
rowSolved = new int[9];
colSolved = new int[9];
subSolved = new int[3][3];
rows = new boolean[9][9];
cols = new boolean[9][9];
subs = new boolean[3][3][9];
int unsolved = 0;
for(int row = 0; row < 9; row ++) {
for(int col = 0; col < 9; col ++) {
if (board[row][col] == '.') {
unsolved ++;
} else {
int num = board[row][col]-'1';
rows[row][num] = true;
cols[col][num] = true;
int subr = row / 3;
int subc = col / 3;
subs[subr][subc][num] = true;
rowSolved[row] ++;
colSolved[col] ++;
subSolved[subr][subc] ++;
}
}
}
cells = new Cell[unsolved];
int cpos = 0;
int priority = -1;
for(int row = 0; row < 9; row ++) {
for(int col = 0; col < 9; col ++) {
if (board[row][col] == '.') {
int subr = row / 3;
int subc = col / 3;
Cell cell = new Cell(row, col, 27-rowSolved[row]-colSolved[col]-subSolved[subr][subc]);
if (priority < 0 || cell.uncertainty < cells[priority].uncertainty) priority = cpos;
cells[cpos++] = cell;
}
}
}
Cell temp = cells[0];
cells[0] = cells[priority];
cells[priority] = temp;
find(board, 0);
}
}
class Cell {
int row, col;
int uncertainty;
Cell(int row, int col, int uncertainty) {
this.row = row;
this.col = col;
this.uncertainty = uncertainty;
}
}