Leetcode 37 Sudoku Solver
阿新 • • 發佈:2018-12-23
Write a program to solve a Sudoku puzzle by filling the empty cells.
A sudoku solution must satisfy all of the following rules:
- Each of the digits
1-9
must occur exactly once in each row. - Each of the digits
1-9
must occur exactly once in each column. - Each of the the digits
1-9
must occur exactly once in each of the 93x3
sub-boxes of the grid.
Empty cells are indicated by the character '.'
.
A sudoku puzzle...
...and its solution numbers marked in red.
Note:
- The given board contain only digits
1-9
'.'
. - You may assume that the given Sudoku puzzle will have a single unique solution.
- The given board size is always
9x9
.
這個題為Leetcode 36 的變形,在原有的基礎上加上了回溯的方法,主流的方法是使用dfs
1)
class Solution{ public void solveSudoku(char[][] board) { Set<Character>[] rows = new HashSet[9]; Set<Character>[] columns = new HashSet[9]; Set<Character>[][] boards = new HashSet[3][3]; for(int i=0; i<9; i++){ rows[i]=new HashSet<>(); columns[i]=new HashSet<>(); } for(int i=0; i<3; i++){ for(int j=0; j<3; j++){ boards[i][j]=new HashSet<>(); } } int left=0; for(int i=0; i<9; i++){ for(int j=0; j<9; j++){ if(board[i][j]=='.') {left++; continue;} //count empty cells rows[i].add(board[i][j]); //records all available chars in rows columns[j].add(board[i][j]); //records all available chars in columns boards[i/3][j/3].add(board[i][j]); //records all available chars in each sub Board } } dfs(rows,columns,boards,board,left); } boolean dfs(Set<Character>[] rows, Set<Character>[] columns, Set<Character>[][] boards,char[][] board, int count){ if(count==0) return true; // once count==0 you filled all the empty cells for(int i=0; i<9; i++){ for(int j=0; j<9; j++){ if(board[i][j]!='.') continue; for(char digit='1'; digit<='9'; digit++){ if(!rows[i].contains(digit) && !columns[j].contains(digit) && !boards[i/3][j/3].contains(digit)){ // if the character does not exist in this row, column and sub board continue board[i][j]=digit; rows[i].add(digit); columns[j].add(digit); boards[i/3][j/3].add(digit); if(dfs(rows,columns,boards,board,count-1)) return true; // count-1 is number of empty cells left rows[i].remove(digit); columns[j].remove(digit); boards[i/3][j/3].remove(digit); board[i][j]='.'; } } if(board[i][j]=='.') return false; } } return false; } }
2)
class Solution {
class Position {
int x, y;
int v;
Position(int x, int y, int v){
this.x = x;
this.y = y;
this.v = v;
}
}
public void solveSudoku(char[][] board) {
int[][] states = new int[9][];
int i,j,v;
List<Position> values = new ArrayList<Position>(81);
for(i=0; i<9; i++){
states[i] = new int[9];
for(j=0; j<9; j++){
if(board[i][j] !='.'){
v = 1 << (board[i][j] - '0' - 1);
states[i][j] = v ^ 0x01FF;
values.add(new Position(i, j, v));
}
}
}
solve(states, values);
for(i=0; i<9; i++){
for(j=0; j<9; j++){
if(board[i][j] == '.'){
board[i][j] = bit2Char(states[i][j]);
}
}
}
}
boolean solve(int[][] states, List<Position> values){
while(!values.isEmpty()){
Position pos = values.remove(values.size() -1);
int br = pos.x/3*3, bc = pos.y/3*3;
boolean b;
for(int k=0; k<9; k++) {
if(k != pos.y) {
b = setBit(states, pos.x, k, pos.v, values);
if(!b) {
values.clear();
return false;
}
}
if(k != pos.x) {
b = setBit(states, k, pos.y, pos.v, values);
if(!b) {
values.clear();
return false;
}
}
if((br+k/3) != pos.x && (br+k%3) != pos.y){
b = setBit(states, br + k/3, bc + k%3, pos.v, values);
if(!b) {
values.clear();
return false;
}
}
}
}
int leastx = -1, leasty = -1, least = 0;
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
int bcnt = bitCount(states[i][j]);
if(bcnt!=8 && bcnt > least) {
leastx = i;
leasty = j;
least = bcnt;
}
}
}
if(least != 0){
int i;
int[][] statesClone = new int[9][];
for(i=0; i<9; i++){
statesClone[i] = new int[9];
}
int t= states[leastx][leasty] ^ 0x01FF, s;
while(t>0){
copyArray(states, statesClone);
s = t;
t &= (t-1);
s ^= t;
statesClone[leastx][leasty] = s ^ 0x01FF;
values.add(new Position(leastx, leasty, s));
if(solve(statesClone, values)) {
copyArray(statesClone, states);
return true;
}
}
return false;
} else {
return true;
}
}
boolean setBit(int[][] states, int i, int j , int v, List<Position> values){
if(bitCount(states[i][j]) == 8){ // conflict happening if existed
return (states[i][j] & v) != 0;
}else {
states[i][j] |= v;
if(bitCount(states[i][j]) == 8){
int nv = states[i][j] ^ 0x01FF; // change 1 to 0, 0 to 1 in the last 8 bits;
values.add(new Position(i, j, nv));
}
return true;
}
}
void copyArray(int[][] src, int[][] dest){
for(int i=0; i<9; i++){
System.arraycopy(src[i], 0, dest[i], 0, 9);
}
}
int bitCount(int n){
int count = 0;
while (n>0) {
n &= (n -1) ;
++count;
}
return count;
}
char bit2Char(int bits){
int i = 0;
for(; i<9 && ((1<<i)&bits)!=0; i++);
return (char)(i+1+'0');
}
}