[leetCode]37. 解数独

在这里插入图片描述

回溯法

class Solution {
    // 一共9行,一行9个数字
    private boolean[][] line =  new boolean[9][9];
    // 一共9列,一列9个数字
    private boolean[][] column = new boolean[9][9];
    // 一共9个九宫格3x3,一个九宫格9个数字,第i行j列个空格位于第 (i/3, j/3) 个九宫格
    private boolean[][][] block = new boolean[3][3][9];
    // 标志位找到结果
    private boolean valid = false;
    // 存储空白格子位置的列表
    private List<int[]> spaces = new ArrayList<>();

    public void solveSudoku(char[][] board) {
        // 遍历数独数组
        for (int i = 0; i < 9; ++i) {
            for (int j = 0; j < 9; ++j) {
                // 将空白格位置加入列表中
                if (board[i][j] == '.')
                    spaces.add(new int[]{i, j});
                else {
                    // 将对应行、列、九宫格设置为true,代表该数字已经使用
                    int digit = board[i][j] - '0' - 1;
                    line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = true;
                }
            }
        }
        dfs(board, 0);
    }

    private void dfs(char[][] board, int pos) {
        // 空白格位置填完,说明找到了答案
        if (pos == spaces.size() ) {
            valid = true;
            return;
        }
        int[] space = spaces.get(pos);
        int i = space[0], j = space[1];
        // 在空白格处枚举每一个数字
        for (int digit = 0; digit < 9 && !valid; digit++) {
            // 如果数字digit在当前行、列、九宫格中均未出现
            if (!line[i][digit] && !column[j][digit] && !block[i / 3][j / 3][digit]) {
                // 满足将三个值置为true,并且填入数字
                line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = true;
                board[i][j] = (char)(digit + '0' + 1);
                // 对下一个空白格进行递归
                dfs(board, pos + 1);
                // 回溯到当前递归层时将三个值重新置为false
                line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = false;
            }
        }
    }
}
posted @ 2020-10-06 10:56  消灭猕猴桃  阅读(106)  评论(0编辑  收藏  举报