/** * 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. * * Tags: Backtracking, Hash Table */ class SudokuSolver { public static void main(String[] args) { char[][] board = { {'.', '.', '9', '7', '4', '8', '.', '.', '.'}, {'7', '.', '.', '.', '.', '.', '.', '.', '.'}, {'.', '2', '.', '1', '.', '9', '.', '.', '.'}, {'.', '.', '7', '.', '.', '.', '2', '4', '.'}, {'.', '6', '4', '.', '1', '.', '5', '9', '.'}, {'.', '9', '8', '.', '.', '.', '3', '.', '.'}, {'.', '.', '.', '8', '.', '3', '.', '2', '.'}, {'.', '.', '.', '.', '.', '.', '.', '.', '6'}, {'.', '.', '.', '2', '7', '5', '9', '.', '.'} }; SudokuSolver s = new SudokuSolver(); s.solveSudoku(board); for (int i = 0; i < board.length; i++) { for (int j = 0; j < board[i].length; j++) { System.out.print(board[i][j] + " "); } System.out.println(); } } int[] row, col, sqr; /** * Use three integer arrays as mask to check whether a move is valid */ public void solveSudoku(char[][] board) { if (board == null || board.length != 9 || board[0].length != 9) return; // initialize row = new int[9]; col = new int[9]; sqr = new int[9]; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (board[i][j] != '.') { int num = board[i][j] -'0'; int k = (i - i % 3) + j / 3; row[i] |= 1 << num; col[j] |= 1 << num; sqr[k] |= 1 << num; // kth's square in board, left to right } } } for (int i = 1; i <= 9; i++) if (helper(board, 0, 0, 0, i)) return; } private boolean helper(char[][] board, int i, int j, int k, int num) { if (j == 9) { // reach rightmost j = 0; i++; // next row } if (i == 9) return true; // reach bottom, finished while (board[i][j] != '.') { // find next blank j = (j + 1) % 9; // move to right if (j % 9 == 0) i++; // next row if (i == 9) return true; // reach bottom } k = (i - i % 3) + j / 3; // kth square // if valid, set masks and board if (isValid(i, j, k, num)) { row[i] |= 1 << num; col[j] |= 1 << num; sqr[k] |= 1 << num; board[i][j] = (char)('0' + num); } else return false; // not valid, return false for (int n = 1; n <= 9; n++) // backtrack the next column if (helper(board, i, j + 1, k, n)) return true; // all possible combinations from this position generated // reset this position row[i] ^= 1 << num; col[j] ^= 1 << num; sqr[k] ^= 1 << num; board[i][j] = '.'; return false; } private boolean isValid(int i, int j, int k, int num) { if ((row[i] & 1 << num) > 0) return false; // both are 1 if ((col[j] & 1 << num) > 0) return false; // both are 1 if ((sqr[k] & 1 << num) > 0) return false; // both are 1 return true; } }