判断一个9*9的数独是否有效的两个思路及JAVA代码

package day06;
//判断一个9*9的熟读是否有效只需要根据以下规则,验证已经填入的数字是否有效即可。
//
//    数字 1-9 在每一行只能出现一次。
//    数字 1-9 在每一列只能出现一次。
//    数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

public class IsValidSudoku {
    public static void main(String[] args) {
        //测试
        char[][] board = {
                {'.','.','.', '.','5','.', '.','1','.'},
                {'.','4','.', '3','.','.', '.','.','.'},
                {'.','.','.', '.','.','3', '.','.','1'},

                {'8','.','.', '.','.','.', '.','2','.'},
                {'.','.','2', '.','7','.', '.','.','.'},
                {'.','1','5', '.','.','.', '.','.','.'},

                {'.','.','.', '.','.','2', '.','.','.'},
                {'.','2','.', '9','.','.', '.','.','.'},
                {'.','.','4', '.','.','.', '.','.','.'},
        };

        //测试思路1
        //boolean res = isValidSudoku(board);
        //测试思路2
        boolean res = isValidSudoku02(board);
        System.out.println(res);

    }
    //思路:遍历该 9 x 9 数独 三 次,以确保:
    //行中没有重复的数字。
    //列中没有重复的数字。
    //3 x 3 子数独内没有重复的数字。

    public static boolean isValidSudoku(char[][] board) {
        //判断行和列
        if( !judgeRowAndCol(board,0,0,board.length, board.length) ) {
            return false;
        } else if (!judgeThree(board)) {
            return false;
        }

        return true;
    }

    public static boolean judgeRowAndCol(char[][] board, int beginRow, int beginCol, int width, int height) {
        HashSet<Character> setRow = new HashSet<>(9);
        HashSet<Character> setCol = new HashSet<>(9);
        for(int i = beginRow; i < width; i ++) {
            setRow.clear();
            setCol.clear();
            for(int j = beginCol; j < width; j ++) {
                //判断行
                if(board[i][j] != '.') {
                    if(setRow.isEmpty()) {
                        setRow.add(board[i][j]);
                    } else if (setRow.contains(board[i][j])) {
                        return false;
                    } else {
                        setRow.add(board[i][j]);
                    }
                }

                //判断列
                if(board[j][i] != '.') {
                    if(setCol.isEmpty()) {
                        setCol.add(board[j][i]);
                    } else if (setCol.contains(board[j][i])) {
                        return false;
                    } else {
                        setCol.add(board[j][i]);
                    }
                }

            }
        }

        return true;
    }

    //判断3*3宫格
    public static boolean judgeThree(char[][] board) {
        HashSet<Character> set = new HashSet<>(9);
        for(int i = 0; i < board.length; i += 3) {
            for(int j = 0; j < board.length; j += 3) {
                set.clear();
                //判断3*3宫格内的每一行,判断三行是否有重复的数字
                for(int m = i; m < i + 3; m ++) {
                    for(int n = j; n < j + 3; n ++) {

                        if(board[m][n] != '.') {
                            if(set.isEmpty()) {
                                set.add(board[m][n]);
                            } else if (set.contains(board[m][n])) {
                                return false;
                            } else {
                                set.add(board[m][n]);
                            }
                        }
                    }
                }
            }
        }

        return true;
    }

    //思路2:根据上面的思路,我们可以在一次遍历中得到结果
    public static boolean isValidSudoku02(char[][] board) {
        //使用Map记录出现的数字及出现的次数
        /*HashMap<Integer, Integer> [] rows = new HashMap[9];
        HashMap<Integer, Integer> [] columns = new HashMap[9];
        HashMap<Integer, Integer> [] boxes = new HashMap[9];
        for (int i = 0; i < 9; i++) {
            rows[i] = new HashMap<Integer, Integer>();
            columns[i] = new HashMap<Integer, Integer>();
            boxes[i] = new HashMap<Integer, Integer>();
        }*/

        //使用List
        ArrayList<Integer>[] row = new ArrayList[9];
        ArrayList<Integer>[] col = new ArrayList[9];
        ArrayList<Integer>[] box = new ArrayList[9];

        for(int i = 0; i < 9; i ++) {
            row[i] = new ArrayList<>(9);
            col[i] = new ArrayList<>(9);
            box[i] = new ArrayList<>(9);
        }
        //根据所在的行i 和 所在的列j 计算出所在的子宫格= (i / 3) * 3  + j / 3
        for(int i = 0; i < board.length; i ++) {
            for(int j = 0; j < board.length; j ++) {
                char num = board[i][j];
                if(num != '.') {
                    int n = (int)num;
                    int box_index = (i / 3) * 3 + j / 3;
                    if(row[i].contains(n) || col[j].contains(n) || box[box_index].contains(n)) {
                        return false;
                    } else {
                        row[i].add(n);
                        col[j].add(n);
                        box[box_index].add(n);
                    }
                }
            }
        }

        return true;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值