解数独sudoku-solver
代码一
package sudoku_solver;
import java. util. ArrayList;
import java. util. List;
public class Solution {
private boolean[ ] [ ] line = new boolean[ 9 ] [ 9 ] ;
private boolean[ ] [ ] column = new boolean[ 9 ] [ 9 ] ;
private boolean[ ] [ ] [ ] block = new boolean[ 3 ] [ 3 ] [ 9 ] ;
private boolean valid = false;
private List< int [ ] > spaces = new ArrayList< int [ ] > ( ) ;
public void solveSudoku ( char [ ] [ ] board) {
for ( int i = 0 ; i < 9 ; ++ i) {
for ( int j = 0 ; j < 9 ; ++ j) {
if ( board[ i] [ j] == '.' ) {
spaces. add ( new int [ ] { i, j} ) ;
} else {
int digit = board[ i] [ j] - '0' - 1 ;
line[ i] [ digit] = column[ j] [ digit] = block[ i / 3 ] [ j / 3 ] [ digit] = true;
}
}
}
dfs ( board, 0 ) ;
}
public void dfs ( char [ ] [ ] board, int pos) {
if ( pos == spaces. size ( ) ) {
valid = true;
return ;
}
int [ ] space = spaces. get ( pos) ;
int i = space[ 0 ] , j = space[ 1 ] ;
for ( int digit = 0 ; digit < 9 && ! valid; ++ digit) {
if ( ! line[ i] [ digit] && ! column[ j] [ digit] && ! block[ i / 3 ] [ j / 3 ] [ digit] ) {
line[ i] [ digit] = column[ j] [ digit] = block[ i / 3 ] [ j / 3 ] [ digit] = true;
board[ i] [ j] = ( char ) ( digit + '0' + 1 ) ;
dfs ( board, pos + 1 ) ;
line[ i] [ digit] = column[ j] [ digit] = block[ i / 3 ] [ j / 3 ] [ digit] = false;
}
}
}
private void printBoard ( char [ ] [ ] board) {
for ( int i = 0 ; i < 9 ; i++ ) {
for ( int j = 0 ; j < 9 ; j++ ) {
System. out. print ( board[ i] [ j] + " " ) ;
}
System. out. println ( ) ;
}
}
public static void main ( String[ ] args) {
char [ ] [ ] board = new char [ ] [ ] {
{ '5' , '3' , '.' , '.' , '7' , '.' , '.' , '.' , '.' } ,
{ '6' , '.' , '.' , '1' , '9' , '5' , '.' , '.' , '.' } ,
{ '.' , '9' , '8' , '.' , '.' , '.' , '.' , '6' , '.' } ,
{ '8' , '.' , '.' , '.' , '6' , '.' , '.' , '.' , '3' } ,
{ '4' , '.' , '.' , '8' , '.' , '3' , '.' , '.' , '1' } ,
{ '7' , '.' , '.' , '.' , '2' , '.' , '.' , '.' , '6' } ,
{ '.' , '6' , '.' , '.' , '.' , '.' , '2' , '8' , '.' } ,
{ '.' , '.' , '.' , '4' , '1' , '9' , '.' , '.' , '5' } ,
{ '.' , '.' , '.' , '.' , '8' , '.' , '.' , '7' , '9' }
} ;
Solution solution = new Solution ( ) ;
solution. printBoard ( board) ;
solution. solveSudoku ( board) ;
solution. printBoard ( board) ;
}
}
代码二
package sudoku_solver;
public class Solution2 {
public void solveSudoku ( char [ ] [ ] board) {
boolean[ ] [ ] row = new boolean[ 9 ] [ 9 ] ;
boolean[ ] [ ] col = new boolean[ 9 ] [ 9 ] ;
boolean[ ] [ ] block = new boolean[ 9 ] [ 9 ] ;
for ( int i = 0 ; i < 9 ; i++ ) {
for ( int j = 0 ; j < 9 ; j++ ) {
if ( board[ i] [ j] != '.' ) {
int num = board[ i] [ j] - '1' ;
row[ i] [ num] = true;
col[ j] [ num] = true;
block[ i / 3 * 3 + j / 3 ] [ num] = true;
}
}
}
dfs ( board, row, col, block, 0 , 0 ) ;
}
private boolean dfs ( char [ ] [ ] board, boolean[ ] [ ] row, boolean[ ] [ ] col, boolean[ ] [ ] block, int i, int j) {
while ( board[ i] [ j] != '.' ) {
if ( ++ j >= 9 ) {
i++ ;
j = 0 ;
}
if ( i >= 9 ) {
return true;
}
}
for ( int num = 0 ; num < 9 ; num++ ) {
int blockIndex = i / 3 * 3 + j / 3 ;
if ( ! row[ i] [ num] && ! col[ j] [ num] && ! block[ blockIndex] [ num] ) {
board[ i] [ j] = ( char ) ( '1' + num) ;
row[ i] [ num] = true;
col[ j] [ num] = true;
block[ blockIndex] [ num] = true;
if ( dfs ( board, row, col, block, i, j) ) {
return true;
} else {
row[ i] [ num] = false;
col[ j] [ num] = false;
block[ blockIndex] [ num] = false;
board[ i] [ j] = '.' ;
}
}
}
return false;
}
private void printBoard ( char [ ] [ ] board) {
for ( int i = 0 ; i < 9 ; i++ ) {
for ( int j = 0 ; j < 9 ; j++ ) {
System. out. print ( board[ i] [ j] + " " ) ;
}
System. out. println ( ) ;
}
}
public static void main ( String[ ] args) {
char [ ] [ ] board = new char [ ] [ ] {
{ '5' , '3' , '.' , '.' , '7' , '.' , '.' , '.' , '.' } ,
{ '6' , '.' , '.' , '1' , '9' , '5' , '.' , '.' , '.' } ,
{ '.' , '9' , '8' , '.' , '.' , '.' , '.' , '6' , '.' } ,
{ '8' , '.' , '.' , '.' , '6' , '.' , '.' , '.' , '3' } ,
{ '4' , '.' , '.' , '8' , '.' , '3' , '.' , '.' , '1' } ,
{ '7' , '.' , '.' , '.' , '2' , '.' , '.' , '.' , '6' } ,
{ '.' , '6' , '.' , '.' , '.' , '.' , '2' , '8' , '.' } ,
{ '.' , '.' , '.' , '4' , '1' , '9' , '.' , '.' , '5' } ,
{ '.' , '.' , '.' , '.' , '8' , '.' , '.' , '7' , '9' }
} ;
Solution2 solution = new Solution2 ( ) ;
solution. printBoard ( board) ;
solution. solveSudoku ( board) ;
solution. printBoard ( board) ;
}
}
代码三——二进制解法
class Solution {
private int [ ] line = new int [ 9 ] ;
private int [ ] column = new int [ 9 ] ;
private int [ ] [ ] block = new int [ 3 ] [ 3 ] ;
private boolean valid = false;
private List< int [ ] > spaces = new ArrayList< int [ ] > ( ) ;
public void solveSudoku ( char [ ] [ ] board) {
for ( int i = 0 ; i < 9 ; ++ i) {
for ( int j = 0 ; j < 9 ; ++ j) {
if ( board[ i] [ j] == '.' ) {
spaces. add ( new int [ ] { i, j} ) ;
} else {
int digit = board[ i] [ j] - '0' - 1 ;
flip ( i, j, digit) ;
}
}
}
dfs ( board, 0 ) ;
}
public void dfs ( char [ ] [ ] board, int pos) {
if ( pos == spaces. size ( ) ) {
valid = true;
return ;
}
int [ ] space = spaces. get ( pos) ;
int i = space[ 0 ] , j = space[ 1 ] ;
int mask = ~ ( line[ i] | column[ j] | block[ i / 3 ] [ j / 3 ] ) & 0x1ff ;
for ( ; mask != 0 && ! valid; mask & = ( mask - 1 ) ) {
int digitMask = mask & ( - mask) ;
int digit = Integer. bitCount ( digitMask - 1 ) ;
flip ( i, j, digit) ;
board[ i] [ j] = ( char ) ( digit + '0' + 1 ) ;
dfs ( board, pos + 1 ) ;
flip ( i, j, digit) ;
}
}
public void flip ( int i, int j, int digit) {
line[ i] ^ = ( 1 << digit) ;
column[ j] ^ = ( 1 << digit) ;
block[ i / 3 ] [ j / 3 ] ^ = ( 1 << digit) ;
}
}
代码四
final int N = 9 ;
private int [ ] rows = new int [ N] ;
private int [ ] cols = new int [ N] ;
private int [ ] [ ] cells = new int [ 3 ] [ 3 ] ;
public void solveSudoku ( char [ ] [ ] board) {
int count = 0 ;
for ( int i = 0 ; i < N; i++ ) {
for ( int j = 0 ; j < N; j++ ) {
char ch = board[ i] [ j] ;
if ( ch == '.' ) {
count++ ;
} else {
fillNumber ( i, j, ch - '1' , true) ;
}
}
}
backtrace ( board, count) ;
}
private boolean backtrace ( char [ ] [ ] board, int count) {
if ( count == 0 ) {
return true;
}
int [ ] pos = getMinOkMaskCountPos ( board) ;
int x = pos[ 0 ] , y = pos[ 1 ] ;
int mask = getMask ( x, y) ;
for ( char c = '1' ; c <= '9' ; c++ ) {
int index = c - '1' ;
if ( testMask ( mask, index) ) {
fillNumber ( x, y, index, true) ;
board[ x] [ y] = c;
if ( backtrace ( board, count - 1 ) )
return true;
board[ x] [ y] = '.' ;
fillNumber ( x, y, index, false) ;
}
}
return false;
}
private void fillNumber ( int x, int y, int n, boolean fill) {
if ( fill) {
int mask = 1 << n;
rows[ x] = rows[ x] | mask;
cols[ y] = cols[ y] | mask;
cells[ x / 3 ] [ y / 3 ] = cells[ x / 3 ] [ y / 3 ] | mask;
} else {
int mask = ~ ( 1 << n) ;
rows[ x] = rows[ x] & mask;
cols[ y] = cols[ y] & mask;
cells[ x / 3 ] [ y / 3 ] = cells[ x / 3 ] [ y / 3 ] & mask;
}
}
private int getMask ( int x, int y) {
return rows[ x] | cols[ y] | cells[ x / 3 ] [ y / 3 ] ;
}
private int getCount ( int mask) {
int count = 0 ;
for ( int i = 0 ; i < N; i++ ) {
if ( ( mask & ( 1 << i) ) == 0 )
count++ ;
}
return count;
}
private boolean testMask ( int mask, int index) {
return ( mask & ( 1 << index) ) == 0 ;
}
private int [ ] getMinOkMaskCountPos ( char [ ] [ ] board) {
int [ ] res = new int [ 2 ] ;
int min = 10 ;
for ( int i = 0 ; i < N; i++ ) {
for ( int j = 0 ; j < N; j++ ) {
if ( board[ i] [ j] == '.' ) {
int mask = getMask ( i, j) ;
int count = getCount ( mask) ;
if ( count < min) {
min = count;
res[ 0 ] = i;
res[ 1 ] = j;
}
}
}
}
return res;
}
sdwwld