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...
思路:回溯(Backtracking),回溯题练得太少,知道应该用回溯写,但不知如何下笔。。。。。
下面代码是参考网上博客写的,回溯题有如下几点需要注意:
1. 应当有个独立的isValid判断函数
2. 递归求解,递归函数应当有返回值来判断当前解是否正确
3. 对当前位置先取一个值,然后判断是否正确,如是,则继续下面的递归;否则,清空刚才赋的值,进行下一次尝试
这里isValid方法我原来是使用的Valid Sudoku的解,提交时发现会超时,参考了下别人的实现发现:有许多的判断是多余的,如:
当在[x][y]出取一个值时,只需要判断x行,y列,以及x,y所处的9宫格中是否valid即可,这样会减少很多无用的判断,代码中注释部分是
原来的实现。比较下可以提高8倍左右。
1 public class Solution { 2 3 public static void main(String[] args) { 4 // TODO Auto-generated method stub 5 char[][] board = new char[][] { "..9748...".toCharArray(), 6 "7........".toCharArray(), ".2.1.9...".toCharArray(), 7 "..7...24.".toCharArray(), ".64.1.59.".toCharArray(), 8 ".98...3..".toCharArray(), "...8.3.2.".toCharArray(), 9 "........6".toCharArray(), "...2759..".toCharArray() }; 10 long start = System.nanoTime(); 11 solveSudokuRecursive(board); 12 long end = System.nanoTime(); 13 System.out.println((end - start) * 1e-6); 14 for (int i = 0; i < 9; i++) { 15 for (int j = 0; j < 9; j++) { 16 System.out.print(board[i][j]); 17 System.out.print(' '); 18 } 19 System.out.println(); 20 } 21 22 } 23 24 public void solveSudoku(char[][] board) { 25 // Start typing your Java solution below 26 // DO NOT write main() function 27 solveSudokuRecursive(board); 28 } 29 30 public static boolean solveSudokuRecursive(char[][] board) { 31 int[] pairs = getFirstEmpty(board); 32 if (pairs[0] == -1 && pairs[1] == -1) 33 return true; 34 for (int i = 1; i <= 9; i++) { 35 board[pairs[0]][pairs[1]] = (char) (i + '0'); 36 if (isValid(board, pairs[0], pairs[1]) 37 && solveSudokuRecursive(board)) { 38 return true; 39 } 40 // backtrack 41 board[pairs[0]][pairs[1]] = '.'; 42 } 43 return false; 44 } 45 46 public static int[] getFirstEmpty(char[][] board) { 47 int[] pairs = null; 48 for (int i = 0; i < 9; i++) { 49 for (int j = 0; j < 9; j++) { 50 if (board[i][j] == '.') { 51 pairs = new int[] { i, j }; 52 return pairs; 53 } 54 } 55 } 56 pairs = new int[] { -1, -1 }; 57 return pairs; 58 } 59 60 /** 61 * reduce some unnecessary compare by transport two parameters 62 * 63 * @param board 64 * @param x 65 * @param y 66 * @return 67 */ 68 public static boolean isValid(char[][] board, int x, int y) { 69 // Set<Character> row = new HashSet<Character>(); 70 // Set<Character> col = new HashSet<Character>(); 71 72 for (int i = 0; i < 9; i++) { 73 if (i != y && board[x][i] == board[x][y]) 74 return false; 75 76 if (i != x && board[i][y] == board[x][y]) 77 return false; 78 } 79 80 // for (int i = 0; i < 9; i++) { 81 // row.clear(); 82 // col.clear(); 83 // for (int j = 0; j < 9; j++) { 84 // if (board[i][j] != '.') { 85 // if (row.contains(board[i][j])) 86 // return false; 87 // else { 88 // row.add(board[i][j]); 89 // } 90 // } 91 // 92 // if (board[j][i] != '.') { 93 // if (col.contains(board[j][i])) 94 // return false; 95 // else 96 // col.add(board[j][i]); 97 // } 98 // 99 // } 100 // } 101 int xIdx = (x / 3) * 3; 102 int yIdx = (y / 3) * 3; 103 for (int m = 0; m < 3; m++) { 104 for (int n = 0; n < 3; n++) { 105 if(m + xIdx != x && n + yIdx != y && board[m + xIdx][n + yIdx] == board[x][y])// 判断9宫格中是否存在board[x][y] 106 return false; 107 } 108 } 109 110 // Set<Character> container = new HashSet<Character>(); 111 // for (int i = 0; i < 9; i += 3) { 112 // for (int j = 0; j < 9; j += 3) { 113 // for (int m = 0; m < 3; m++) { 114 // for (int n = 0; n < 3; n++) { 115 // if (board[m + i][n + j] == '.') { 116 // continue; 117 // } 118 // if (container.contains(board[m + i][n + j])) 119 // return false; 120 // else { 121 // container.add(board[m + i][n + j]); 122 // } 123 // } 124 // 125 // } 126 // container.clear(); 127 // } 128 // } 129 return true; 130 } 131 }