37. 解数独
Tag: BackTracing
Difficulty Hard
Link https://leetcode-cn.com/problems/sudoku-solver/
思路:
class Solution {
public void solveSudoku(char[][] board) {
// 记录每行1-9的使用情况 第i行0-8分别表示1-9是否被使用
boolean[][] row = new boolean[9][9];
// 列同理
boolean[][] col = new boolean[9][9];
// 将每个3*3小方格转化成行,共9行
boolean[][] box = new boolean[9][9];
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (board[i][j] != '.') {
// char转整数,1-9变为数组下标0-8
int num = board[i][j] - '1';
// 元素在第几个小方格就在box的第几行
int k = (i / 3) * 3 + (j / 3);
row[i][num] = col[j][num] = box[k][num] = true;
}
}
}
solveSudokuHelper(board, row, col, box, 0);
}
public boolean solveSudokuHelper(char[][] board, boolean[][] row, boolean[][] col, boolean[][] box, int n) {
// 使用n来表示填充情况,81表示填满,退出
if (n == 81) {
return true;
}
// 获取当前要填充的位置 第i行第j列 以及元素在第k个小方格
int i = n / 9;
int j = n % 9;
int k = (i / 3) * 3 + (j / 3);
if (board[i][j] != '.') {
return solveSudokuHelper(board, row, col ,box, n + 1);
}
for (int num = 0; num < 9; num++) {
// 数字被使用过,跳过
if (row[i][num] || col[j][num] || box[k][num]) continue;
board[i][j] = (char) (num + '1');
row[i][num] = col[j][num] = box[k][num] = true;
if (solveSudokuHelper(board, row, col, box, n + 1)) {
return true;
}
// 如果填充失败,需要回溯,恢复原有状态
row[i][num] = col[j][num] = box[k][num] = false;
}
// 回溯
board[i][j] = '.';
return false;
}
}