我的LeetCode代码仓:https://github.com/617076674/LeetCode
原题链接:https://leetcode-cn.com/problems/sudoku-solver/description/
题目描述:
知识点:递归,回溯
思路:利用回溯法对于每一个待填充位置都尝试着填充合法的值
(1)新建一个成员变量retBoard,该成员变量是一个char类型的二维数组,数组维数是9 × 9的。新建一个内部类Point,该类有两个成员变量i和j,分别记录点的横、纵坐标,并有一个带参数的构造方法可以给i和j变量赋初值。
(2)遍历整个九宫格,寻找到其中内容为'.'的点,并将其坐标作为参数新建一个Point类型的对象将其加入到一个ArrayList<Point>类型的数组arrayList中,该数组用以记录需要填充的格子的点。
(3)调用函数fillNumber(char[][] board, ArrayList<Point> arrayList, int index)来给arrayList的第index个点赋值。在该函数中,递归地为整张九宫格中的'.'填充新的数字。
a.如果index == arrayList.size(),我们用retBoard数组记录下board数组中各个元素的值,并返回。
b.遍历数字1 - 9,如果arrayList中第index个点的坐标所对应的位置可以填充,就修改board对应位置的值,并尝试着递归地调用fillNumber函数填充下一个点。注意在递归调用之后,如果该方向是错误的,需要注意函数回溯过程时变量的回溯,需要将board对应位置的值重新置为'.'。
该思路因为需要递归调用函数n次,每次递归调用最多有9个方向可以走,所以时间复杂度为O(9 ^ n),其中n为九宫格中'.'的数量。空间复杂度即递归深度,为O(n)。
JAVA代码:
public class Solution {
private char[][] retBoard = new char[9][9];
private class Point {
int i;
int j;
public Point(int i, int j) {
this.i = i;
this.j = j;
}
}
public void solveSudoku(char[][] board) {
//在arrayList中保存需要填充的空格的横坐标和纵坐标
ArrayList<Point> arrayList = new ArrayList<>();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if(board[i][j] == '.')
arrayList.add(new Point(i, j));
}
}
fillNumber(board, arrayList, 0);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
board[i][j] = retBoard[i][j];
}
}
}
//将要给arrayList中的第index个点进行填充值
private void fillNumber(char[][] board, ArrayList<Point> arrayList, int index) {
if(index == arrayList.size()) {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
retBoard[i][j] = board[i][j];
}
}
return;
}
int indexi = arrayList.get(index).i;
int indexj = arrayList.get(index).j;
for (int num = 1; num <= 9; num++) {
if(canFillThisNum(board, indexi, indexj, num)) {
board[indexi][indexj] = String.valueOf(num).charAt(0);
fillNumber(board, arrayList, index + 1);
board[indexi][indexj] = '.';
}
}
}
private boolean canFillThisNum(char[][] board, int i, int j, int num) {
if(board[i][j] != '.') {
return false;
}
HashSet<Character> hashSet = new HashSet<>();
for (int k = 0; k < 9; k++) {
if(board[i][k] != '.') {
hashSet.add(board[i][k]);
}
if(board[k][j] != '.') {
hashSet.add(board[k][j]);
}
}
for (int k = (i / 3) * 3; k <= (i / 3) * 3 + 2; k++) {
for (int p = (j / 3) * 3; p <= (j / 3) * 3 + 2; p++) {
if(board[k][p] != '.') {
hashSet.add(board[k][p]);
}
}
}
if(hashSet.contains(String.valueOf(num).charAt(0))) {
return false;
}
return true;
}
}
LeetCode解题报告: