题目
编写一个程序,通过已填充的空格来解决数独问题。
一个数独的解法需遵循如下规则:
数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。
答案被标成红色。
Note:
给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
方案:回朔法
- 思路比较简单:每走一格就判断是否存在满足条件的数,如果没有,那么就回朔上一格,有则走下一格
- 这边为了偷懒用了三个HashMap存放每行、列、块已用过的数,用别的数据结构也可以达到同样的效果,而且应该会更优,我这个是懒得改了。
- 顺手封装了几个方法优化了下结构,刚写完的时候这个代码结构真的没法看
class Solution {
private HashMap<Character, Integer>[] col = new HashMap[9];
private HashMap<Character, Integer>[] row = new HashMap[9];
private HashMap<Character, Integer>[] chunk = new HashMap[9];
public void solveSudoku(char[][] board) {
initHash(board);
recall(board, 0, 0);
return;
}
public boolean recall(char[][] board, int rowstart, int colstart) {
if (board[rowstart][colstart] != '.') {
if (colstart == 8 && rowstart == 8) return true;
else if (colstart == 8 && rowstart < 8) return recall(board, rowstart + 1, 0);
else return recall(board, rowstart, colstart + 1);
} else {
for (char i = '1'; i <= '9'; i++) {
if (check(rowstart, colstart, i)) {
putIntoHash(rowstart, colstart, i);
board[rowstart][colstart] = i;
if (colstart == 8 && rowstart == 8) return true;
else if (colstart == 8 && rowstart < 8) {
if (recall(board, rowstart + 1, 0)) return true;
} else if (recall(board, rowstart, colstart + 1)) return true;
removeFromHash(board, rowstart, colstart, i);
}
}
}
return false;
}
public void initHash(char[][] board) {
for (int i = 0; i < 9; i++) {
row[i] = new HashMap<>( );
col[i] = new HashMap<>( );
chunk[i] = new HashMap<>( );
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == '.') continue;
else if (board[i][j] <= '9' && board[i][j] >= 1) {
row[i].put(board[i][j], 1);
col[j].put(board[i][j], 1);
chunk[(i / 3) * 3 + j / 3].put(board[i][j], 1);
}
}
}
}
public void putIntoHash(int rowstart, int colstart, char target) {
row[rowstart].put(target, 1);
col[colstart].put(target, 1);
chunk[(rowstart / 3) * 3 + colstart / 3].put(target, 1);
}
public void removeFromHash(char[][] board, int rowstart, int colstart, char target) {
board[rowstart][colstart] = '.';
row[rowstart].remove(target);
col[colstart].remove(target);
chunk[(rowstart / 3) * 3 + colstart / 3].remove(target);
}
public boolean check(int i, int j, char target) {
if (col[j].get(target) != null) return false;
if (row[i].get(target) != null) return false;
if (chunk[(i / 3) * 3 + j / 3].get(target) != null) return false;
return true;
}
}
复杂度计算:
- 时间复杂度:计算最坏情况是981
- 空间复杂度:共有:8123个临时变量,也就是三个HashMap,也就是O(1)