class Solution {
    /**
     * 检查在数独(x,y)处填入num,是否合法
     * @param board 数独
     * @param x x
     * @param y y
     * @param num 要检测的数字
     * @return 是否合法
     */
    private boolean checkLegal(char[][] board, int x, int y, char num){
        // 检查同一列中是否存在相同数字
        for (char[] chars : board) {
            if (chars[x] == num) {
                return false;
            }
        }

        // 检查同一行中是否存在相同数字
        for (int i = 0; i < board[y].length; i++) {
            if(board[y][i] == num){
                return false;
            }
        }

        // 检查同一9宫格内是否存在相同数字
        int left = (x / 3) * 3;
        int top = (y / 3) * 3;
        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if(board[top+i][left+j] == num){
                    return false;
                }
            }
        }

        // 都没有,则合法
        return true;
    }

    /**
     * 从数独(x,y)处开始填入数字
     * @param board 数独
     * @param x x
     * @param y y
     * @return 是否有解
     */
    public boolean solve(char[][]board, int x, int y){
        // x超出范围,从下一行开头开始填
        if(x >= board[0].length){
            x = 0;
            y++;
        }
        // y超出范围,说明已填完
        if(y>=board.length){
            return true;
        }

        // 当前坐标需要填入数字
        if(board[y][x]=='.'){
            // 遍历1-9
            for (char k = '1'; k <= '9'; k++) {
                // 如果当前坐标可以填入k
                if(checkLegal(board, x, y, k)){
                    // 填入k
                    board[y][x] = k;
                    // 继续填下一个坐标的值,并判断之后的坐标是否有解
                    if(solve(board, x+1, y)){
                        // 如果之后的坐标有解,那么k值是对的,直接返回
                        return true;
                    }
                    // 否则说明填入k值无解,清空填入的k值
                    board[y][x] = '.';
                }
            }
            // 1-9都无解,返回无解
            return false;
        } else {
            // 当前坐标已有数字,则继续遍历下个坐标
            return solve(board, x+1, y);
        }
    }

    public void solveSudoku(char[][] board) {
        solve(board, 0, 0);
    }
}