Sudoku Verification*-可解的数独

有效数独和解数独 Sudoku Verification*


题目 English

这是悉尼大学的一个challenge,完成了所有的test case
在这里插入图片描述
You are tasked with writing a program that will verify that a sudoku puzzle is solvable. If you are unfamiliar with sudoku, Sudoku is a puzzle game that requires the player to place numbers in a cell that do not:

  • Repeat on the same row

  • Repeat on the same column

  • Repeat within an 3x3 space.

A sudoku grid dimensions are multiples of 3, This means that both the length and height of the board have to be divisable by 3. In this case, we will be denoting empty spaces in the board using null.

You are required to implement the method boolean isSolvable(Integer[][] board) that will check to see if a sudoku puzzle is solvable. You are encouraged to use backtracking (a kind of bruteforcing technique) for solving this problem.

题目

你的任务是编写一个程序来验证数独谜题是否可解。如果你不熟悉数独,数独是一种益智游戏,要求玩家在格子中放置数字,这些数字不能:

  • 在同一行重复

  • 在同一栏重复

  • 在3x3的空间内重复。

数独网格的尺寸是3的倍数,这意味着棋盘的长度和高度都必须能被3整除。在这种情况下,我们将使用null表示板中的空白空间。

您需要实现boolean isSolvable(Integer[][] board)方法,该方法将检查数独谜题是否可解。我们鼓励您使用回溯(一种强制执行技术)来解决这个问题。

解决思路

数独是否是一个可解的数独,分为两个步骤

  • 1 对已经填入的数字判断,是否是一个有效的数独
public static boolean isEffectable(Integer[][] board){
        if(board == null || board.length % 3 !=0 || board[0].length %3!=0)
            //不能被3整除 无效
            return false;
        int row = board.length;
        int col = board[0].length;
        for(int i = 0; i<board.length; i++){
            if(board[i].length != col) return false;
        }
        boolean[][] rows = new boolean[row][9];
        boolean[][] cols = new boolean[col][9];
        boolean[][] block = new boolean[(row / 3) * (col / 3)][9];

        for(int i = 0; i < row; i++){ // 当前元素的行
            for(int j = 0; j < col; j++){  // 当前元素的列
                if(board[i][j] !=null){
                    int c = board[i][j];
                    if(rows[i][c - 1] || cols[j][c -1 ]|| block [i/3 * 3 + j/3][c-1]){
                        return false;
                    }
                    rows[i][c - 1] = true;
                    cols[j][c -1 ] = true;
                    block[i/3 *3+j/3][c - 1] = true;
                }
            }
        }
        return true;
    }
  • 2 对null的位置填入数字,判断整个数独是否可解
 public static boolean backStrack(Integer[][] board){
        //  求一个解
        int row = board.length;
        int col = board[0].length;
        for(int i = 0; i < row; i++ ){
            for(int j = 0; j < col; j++){
                if(board[i][j] == null){
                    for(int k = 1; k <= 9; k++){
                        if(check(i,j,k,board)){
                            board[i][j] = k;
                            if(backStrack(board))
                                return true;
                            board[i][j] = null;
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }

    public static boolean check(int i, int j, int k, Integer[][] board){
        int row = board.length;
        int col = board[0].length;
        for(int t = 0; t < row; t++){
            System.out.println(t);
            System.out.println(board[t][j]);
            if( board[t][j] !=null &&  board[t][j] == k) return false;
        }
        for(int t = 0; t < col; t ++){
            if(board[i][t]!=null && board[i][t]  == k) return false;
        }
        int boxrow = i/3 * 3;
        int boxcol = j/3 * 3;
        for(int t = boxrow; t < boxrow + 3; t++){
            for(int f = boxcol; f < boxcol + 3; f++){
                if(board[t][f] !=null && board[t][f] == k)
                    return false;
            }
        }
        return true;
    }
  • 3 整合
public static boolean isSolvable (Integer[][] board){
       // 判断是否有效
        //判断是否可解
        if(!isEffectable(board))
            return false;
        return backStrack(board);
    }
  • 4 全代码
public class SudokuSolve {
    public static void main(String[] args) {
        //Write some tests if you want check here or change b
        Integer[][] b = {
                { 1, 2, 3,5,4,6},
                { null, null, 7,8,9,1},
                { null, null, null,3,7,2}
        };

        System.out.println(isSolvable(b));
    }
    public static boolean isSolvable (Integer[][] board){
       // 判断是否有效
        //判断是否可解
        if(!isEffectable(board))
            return false;
        return backStrack(board);
    }

    public static boolean isEffectable(Integer[][] board){
        if(board == null || board.length % 3 !=0 || board[0].length %3!=0)
            //不能被3整除 无效
            return false;
        int row = board.length;
        int col = board[0].length;
        for(int i = 0; i<board.length; i++){
            if(board[i].length != col) return false;
        }
        boolean[][] rows = new boolean[row][9];
        boolean[][] cols = new boolean[col][9];
        boolean[][] block = new boolean[(row / 3) * (col / 3)][9];

        for(int i = 0; i < row; i++){ // 当前元素的行
            for(int j = 0; j < col; j++){  // 当前元素的列
                if(board[i][j] !=null){
                    int c = board[i][j];
                    if(rows[i][c - 1] || cols[j][c -1 ]|| block [i/3 * 3 + j/3][c-1]){
                        return false;
                    }
                    rows[i][c - 1] = true;
                    cols[j][c -1 ] = true;
                    block[i/3 *3+j/3][c - 1] = true;
                }
            }
        }
        return true;
    }

    public static boolean backStrack(Integer[][] board){
        //  求一个解
        int row = board.length;
        int col = board[0].length;
        for(int i = 0; i < row; i++ ){
            for(int j = 0; j < col; j++){
                if(board[i][j] == null){
                    for(int k = 1; k <= 9; k++){
                        if(check(i,j,k,board)){
                            board[i][j] = k;
                            if(backStrack(board))
                                return true;
                            board[i][j] = null;
                        }
                    }
                    return false;
                }
            }
        }
        return true;
    }

    public static boolean check(int i, int j, int k, Integer[][] board){
        int row = board.length;
        int col = board[0].length;
        for(int t = 0; t < row; t++){
            if( board[t][j] !=null &&  board[t][j] == k) return false;
        }
        for(int t = 0; t < col; t ++){
            if(board[i][t]!=null && board[i][t]  == k) return false;
        }
        int boxrow = i/3 * 3;
        int boxcol = j/3 * 3;
        for(int t = boxrow; t < boxrow + 3; t++){
            for(int f = boxcol; f < boxcol + 3; f++){
                if(board[t][f] !=null && board[t][f] == k)
                    return false;
            }
        }
        return true;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值