93.有效的数独

一、题目描述

请你判断一个 9x9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
数独部分空格内已填入了数字,空白格用 ‘.’ 表示。

注意:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
在这里插入图片描述
在这里插入图片描述

二、解题思路

这道题需要使用一些技巧来计算,题目中给了三个条件,那么我们就直接根据每个条件来直接模拟。

技巧:申请一个9*9的数组,初始化都是F(false),将原始数组中的每个元素值找到新数组中对应的列索引,如果有元素值就将其改为T,表示出现了一次,什么意思呢?下面举例说明:
在这里插入图片描述

第一个条件:数字 1-9 在每一行只能出现一次。

左右两边的行是一一对应的,首先来看第一行的第一个元素5,它的索引应该是4,那么就将右边矩阵第一行对应的索引4(其实也代表第四列)下的F改成T,表示5出现了一次。

再来看第一行的第二个元素3,它的索引应该是2(也相当于第二列),那么就将右边矩阵第一行对应的索引2下的F改成T,表示3出现了一次。依次类推(这里就举两行的例子):

在这里插入图片描述

第二个条件:数字 1-9 在每一列只能出现一次。

跟上面一样,只不过这里不在是左边一行对应右边一行,而是左边一列对应右边一行,这里还是只拿初始矩阵的两列作为例子。首先还是来看第一列的第一个元素5,在右边矩阵中还是来看第一行,元素5对应的索引是4,所以将第一行第四列也就是坐标(0,4)改成T,表示5出现了一次。

再来看第一列的第二个元素6,对应的索引是5,所以将第一行第五列也就是坐标(0,5)改成T,表示5出现了一次,以此类推,左边矩阵第二列对应右边矩阵第二行的元素:
在这里插入图片描述

第三个条件:数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

怎么划分宫格呢,将每个3*3的块看成整体,第一列从上往下是1,2,3宫格,第二列是4,5,6宫格,第三列是7,8,9宫格,每个宫格1到9的元素对应右边矩阵每一行0到8的索引。

某个元素对应的是哪个宫格有一个计算公式:boxIndex = row/3 + (col/3)*3

首先先来看左边矩阵的第一行元素5和3,这都是第一宫格的,直接就看出来了,不用通过公式计算。第一个宫格对应右边矩阵的第一行,那么将第一行元素的第4和第2列位置改成T,说明5和3个出现了一次。

再来看左边矩阵的元素7,它的坐标是row=0,col=4,通过上面的公式boxIndex =0/3+(4/3)*3 = 3,说明该元素出现在第四个宫格,对应右边矩阵的第四行,所以将右边矩阵第四行六列改为T。

依次类推,这里就以左边矩阵前三行为例:
在这里插入图片描述

三、代码演示

class Solution {
    public boolean isValidSudoku(char[][] board) {
        //首先初始化三个9*9的数组
        //表示每一行1-9出现次数的情况
        boolean[][] rowUsed = new boolean[9][9];
        //表示每一列1-9出现次数的情况
        boolean[][] colUsed = new boolean[9][9];
        //表示每一宫格1-9出现次数的情况
        boolean[][] boxUsed = new boolean[9][9];

        //遍历数组
        for (int row=0; row<board.length; row++){
            for (int col=0; col<board[0].length; col++){
                //如果当前元素是数字
                if (board[row][col] != '.'){
                    //先将字符类型转成int类型
                    int num = board[row][col] - '1';

                    //判断这个数字在新数组中的行是否出现了
                    if (rowUsed[row][num]){
                        return false;
                    }else {
                        rowUsed[row][num] = true;
                    }

                    //判断这个数字在新数组中的行是否出现了
                    if (colUsed[col][num]){
                        return false;
                    }else {
                        colUsed[col][num] = true;
                    }

                    //判断宫格
                    int boxIndex = row/3 + (col/3)*3;
                    if (boxUsed[boxIndex][num]){
                        return false;
                    }else {
                        boxUsed[boxIndex][num] = true;
                    }
                }
            }
        }
        return true;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值