37. 解数独
编写一个程序,通过填充空格来解决数独问题。

一个数独的解法需遵循如下规则:

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
空白格用 '.' 表示。

一个数独。

答案被标成红色。

提示:

给定的数独序列只包含数字 1-9 和字符 '.' 。
你可以假设给定的数独只有唯一解。
给定数独永远是 9x9 形式的。
解题思路
利用回溯算法的思想:先遍历每行,行完了再遍历下一行
如果到最后一列,则换下一行
如果到最后一行,则说明找到了可信解,返回true
如果该位置已经有值,则跳出
然后遍历1-9九个选择
判断当前字符是否合法,合法则先选,再递归,再撤销选择
合法性判断:同行、同列或者3*3内没有
图片说明

class Solution {
    char[] nums=new char[]{'1','2','3','4','5','6','7','8','9'};    
    public void solveSudoku(char[][] board) {
        backtrack(board,0,0);
    }
    public boolean backtrack(char[][] board,int i,int j){
        if(i>=board.length)  return true;
        //换下一行
        if(j>=board[0].length)  return backtrack(board,i+1,0);
        //有数字则跳过
        if(board[i][j] != '.')   return backtrack(board,i,j+1);
        for(char ch:nums){
            if(!isVaild(board,i,j,ch)){
                continue;//不合法则继续
            }
            board[i][j]=ch;
            if(backtrack(board,i,j+1)){
                return true;
            }
            board[i][j]='.';
        }
        return false;
    }
    public boolean isVaild(char[][] board,int r,int c,char n){
        for (int i = 0; i < 9; i++) {
            // 判断行是否存在重复
            if (board[r][i] == n) return false;
            // 判断列是否存在重复
            if (board[i][c] == n) return false;
            // 判断 3 x 3 方框是否存在重复
            if (board[(r/3)*3 + i/3][(c/3)*3 + i%3] == n)
                return false;
        }
        return true;
    }
}