【算法题解6】-有效的数独

tags:
- 暴力解法
categories:
- 算法题解

算法题解第六题:判断给出的数独是否有效

题目

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

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
数独示例图

示例 1:
输入:
[
[“5”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: true

示例 2:
输入:
[
[“8”,“3”,".",".",“7”,".",".",".","."],
[“6”,".",".",“1”,“9”,“5”,".",".","."],
[".",“9”,“8”,".",".",".",".",“6”,"."],
[“8”,".",".",".",“6”,".",".",".",“3”],
[“4”,".",".",“8”,".",“3”,".",".",“1”],
[“7”,".",".",".",“2”,".",".",".",“6”],
[".",“6”,".",".",".",".",“2”,“8”,"."],
[".",".",".",“4”,“1”,“9”,".",".",“5”],
[".",".",".",".",“8”,".",".",“7”,“9”]
]
输出: false
解释: 除了第一行的第一个数字从 5 改为 8 以外,空格内其他数字均与 示例1 相同。
但由于位于左上角的 3x3 宫内有两个 8 存在, 因此这个数独是无效的。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/valid-sudoku
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

###解法1:暴力解法
题目要求只需要对给出的数据进行判断是否有效,并不需要判断是否有解。因此一种暴力解法就是对给出三个条件:
1.每行没有重复数字
2.每列没有重复数字
3.每个3*3的小区域没有重复数字
进行实现既可,当输入同时满足以上三个条件时才返回True,否则返回False

    def isValidSudoku(self, board: List[List[str]]) -> bool:
        def judgeRow(board: List[List[str]]): #判断行函数
            for i in range(9):                #设置一个空集合,查看每行元素是否有重复,遍历完一行后清空
                s = set() 
                for j in range(9):        
                    if board[i][j] == ".":
                        continue
                    if board[i][j]  in s:
                        return False
                    else:
                        s.add(board[i][j])
                s.clear()
            return True
        def judgeCol(board:List[List[str]]): #判断列函数
            for i in range(9):               #设置一个空集合,查看每行元素是否有重复,遍历完一行后清空
                s = set()
                for j in range(9):
                    if board[j][i] == ".":
                        continue
                    if board[j][i]  in s:
                        return False
                    else:
                        s.add(board[j][i])
                s.clear()
            return True
        def judgeBlock(board:List[List[str]]): #判断小区域函数:
            for i in range(3):       #i,j表示外部坐标,即位于哪个区块         
                for j in range(3):
                    s = set()
                    for k in range(9):
                        x = k//3     #x,y表示区块内的坐标
                        y = k%3      #合并得到[3*i+x][3*j+y]就是当前坐标
                        if board[3*i+x][3*j+y] == ".":
                            continue
                        if board[3*i+x][3*j+y]  in s:
                            return False
                        else:
                            s.add(board[3*i+x][3*j+y])
                    s.clear()
            return True
        if ( judgeCol(board) and judgeRow(board) and judgeBlock(board)): #三个条件联立判断
             return True
        return False

解法2:位运算
上面方法效率不高,所以在看题解时看到一位大佬写的位运算方法解题,大开眼界。不过大佬写的是java版,这里写一个自己理解的python
版尝试实现。
原作者:parsee
链接:https://leetcode-cn.com/problems/valid-sudoku/solution/javabian-ma-yong-intbiao-shi-ji-he-yong-wei-yun-su/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数独算法说明:用三个二维数组记录数独每个点的状态,SD(i, j)显示数值,也是真实数值(1到9)。ST(i, j)状态,1可由用户输入,2是题目给定的,不能改。SY(i, j)这符串,记录每个点中可能的值。 1、在进行自动计算时,只计算ST(i, j)为1的点,首先将所有状态为1的点的SY(i, j)值全部设为"123456789",SD(i, j)值全部设为0 2、逐点扫描,找到一个点,然后将该点所在的行、列、区域中已存在的SD(x, y)值从SY(i, j)中删除,因为数独规则是一个数值,在行、列、区域都不重复。 3、经第二步处理后,SY(i, j)为空,说明题目错误,SY(i, j)值为一位数字,就说明该点的值是唯一的,可以确定了。 4、剩余的SY(i, j)值最少也是二个数字的,或更多位数。随机从这些两位数的SY(i, j)中选取一个点。取其中的一位确定为该点的值后,重复第2步。如果错误遇错,则重复执行第4步。直到所有点都被确定。 注意:第2步是需要多次重复执行的,所有可用递归函数完成。如果执行结果出现错误(某数出现重复,或某点无值),需要对该过程所执行的所有操作进行回退。 第4步也是需要重复执行的。本和序用Goto跳转方式实现多次执行。 简单的数独,要么所有的点都具有独一值,第1步执行完成后,就已全部完成。或者具有多个,随意猜测一个二位数的SY(i, j)的值都能成功。 难的数独,是可唯一确定的点很少,大部分点都有两种或多种可能的值,但最终正确答案只有一种或很少种。 软件在自动计算过程中,具有很大的偶然性,对于骨灰级的数独题目在计算过程中,时间短的可能不到1秒就能完成,长的可能要几分钟,需要将各种可能性都测试一遍才有结果。 只要题目正确,多计算几次就能得到答案。 程序只处理有两种可能值的情况,对只存在三种可能值的情况未进一步处理,该情况非常极端了。 软件中包含网上下载的200个数独题目。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值