【回溯】37. 解数独

37. 解数独

解题思路

  • 通过solveSudoku方法开始求解数独问题,然后调用backtrack方法进行递归回溯搜索。backtrack方法通过两个参数i和j来确定当前搜索的位置。

  • 在backtrack方法中,首先检查当前位置是否超出了数独的边界,若超出,则表示已经搜索完整个数独,返回true。然后检查当前位置是否已经填入数字,若已填入,则跳到下一个位置进行搜索。接着,遍历尝试填入数字1到9,若遇到不合法的数字,则跳过,继续尝试下一个数字。若尝试填入的数字是合法的,则将该数字填入当前位置,并继续递归地向下搜索。若搜索到底部并找到解,则返回true;若没有找到解,则撤销当前选择的数字,回溯到上一步。若遍历完所有数字仍未找到解,则返回false。

  • isValid方法用于检查当前填入的数字是否符合数独的规则。它检查当前位置所在的行、列以及对应的3×3方格是否存在重复的数字。若存在重复,则返回false;否则返回true。

class Solution {
    public void solveSudoku(char[][] board) {
        backtrack(board,0,0);
    }


    boolean backtrack(char[][] board,int i,int j){
        int m = 9;
        int n = 9;

        if(j == n){
            // 穷举到最后一列 直接换行开始
            return backtrack(board,i + 1,0);
            
        }

        if(i == m){
            return true;// 找到一个可行解
        }

        // 如果该位置是预设的数字 
        if(board[i][j] != '.'){
            return backtrack(board,i,j + 1);
        }

        for(char ch = '1'; ch <= '9'; ch++){
            // 遇到不合法的数字  直接跳过
            if(!isValid(board,i,j,ch)){
                continue;
            }

            board[i][j] = ch;// 进行选择
            if(backtrack(board,i, j+ 1)){
                return true;
            }
            board[i][j] = '.';// 撤销选择
        }

        return false;
    }

    boolean isValid(char[][] board,int r,int c,char n){
        // 判断字符是否可以填入
        for(int i = 0; i < 9; i++){
            // 判断第r行是否有重复字符
            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;
    }
}

你可能感兴趣的:(#,Leetcode,算法,java,数据结构)