leetcode 37. 解数独【回溯】

解数独也是一个典型的回溯算法问题。
首先建立三个数组来记录数独中的行、列和方格中出现过的数字。
然后套用回溯算法的模板,首先处理结束条件,当整个矩阵被遍历完后,返回true值退出回溯过程。当矩阵的当前位置存在数字时,递归调用回溯方法遍历下一个位置,直到遇到矩阵中没有数字的元素时,利用先前建立的三个数组进行判断并剪枝,若最终符合条件,则在当前位置添加新的数字,并继续递归调用回溯方法遍历下一个元素,最后撤回修改操作。

class Solution {
    public void solveSudoku(char[][] board) {
        //定义三个数组记录行、列和方格中出现过的数字
        boolean[][] rowUsed = new boolean[9][10];
        boolean[][] colUsed = new boolean[9][10];
        boolean[][][] blockUsed = new boolean[3][3][10];
        for(int i=0; i<9; i++){
            for(int j = 0; j<9; j++){
                int num = board[i][j] - '0';
                if(num >=1 && num<=9){
                    rowUsed[i][num] = true;
                    colUsed[j][num] = true;
                    blockUsed[i/3][j/3][num] = true; 
                }

            }
        }
       
        backtrack(board, rowUsed, colUsed, blockUsed, 0, 0);
    }
   
    public boolean backtrack(char[][] board, boolean[][] rowUsed, 
                             boolean[][] colUsed, boolean[][][] blockUsed, int row, int col){
// 边界校验, 如果已经填充完成, 返回true, 表示一切结束
        if(col == board[0].length){
            col = 0;
            row++;
            if(row == board.length){
                return true;
            }
        }
        // 是空则尝试填充, 否则跳过继续尝试填充下一个位置
        if(board[row][col] == '.') {
            // 尝试填充1~9
            for(int num = 1; num <= 9; num++){
                boolean canUsed = !(rowUsed[row][num] || colUsed[col][num] || blockUsed[row/3][col/3][num]);
                if(canUsed){
                    rowUsed[row][num] = true;
                    colUsed[col][num] = true;
                    blockUsed[row/3][col/3][num] = true;
                    
                    board[row][col] = (char)('0' + num);
                    if(backtrack(board, rowUsed, colUsed, blockUsed, row, col + 1)){
                        return true;
                    }
                    board[row][col] = '.';
                    
                    rowUsed[row][num] = false;
                    colUsed[col][num] = false;
                    blockUsed[row/3][col/3][num] = false;
                }
            }
        } else {
            return backtrack(board, rowUsed, colUsed, blockUsed, row, col + 1);
        }
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值