力扣(leetcode) 36. 有效的数独(暴力法)(哈希表套列表法)

题目在这:https://leetcode-cn.com/problems/valid-sudoku/

法一:(暴力法)

思路分析:

首先想到使用暴力法解决这道题。
1.建立函数一个函数用于判断整行数组是否有重复数字。
2.将整个二维数组遍历,每一行都调用该函数进行判断是否有重复数字,
3.然后转置整个数组,继续上面的步骤。(相当于判断了每列是否有重复数字)
4.然后再逐个切片出来每一个九宫格,继续拿去判断。

这样比较麻烦,但是属于首先当道的比较容易明白的暴力法。

完整代码:

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        from  collections import  Counter

        import  numpy as np

        def Judge(board):  # 用于判断所有横向数组中是否有重复的元素
            for i in board:
                hash_i = Counter(i)
                for j in hash_i:
                    if j != '.':
                        if hash_i[j] > 1:
                            return False
            return True
        def Slice(ll):  # 用于单行判断
            hash_j = Counter(ll)
            for j in hash_j:
                if j != '.':
                    if hash_j[j] > 1:
                        return False
            return True


        if __name__ == '__main__':

           
            np_board_T = np.array(board).T
            res = np.array(board)


            return (
                Judge(board)
                and Judge(np_board_T)
                and Slice(res[6:9,0:3].flatten().tolist())
                and Slice(res[6:9,3:6].flatten().tolist())
                and Slice(res[6:9,6:9].flatten().tolist())

                and Slice(res[0:3,0:3].flatten().tolist())
                and Slice(res[0:3,3:6].flatten().tolist())
                and Slice(res[0:3,6:9].flatten().tolist())

                and Slice(res[3:6,0:3].flatten().tolist())
                and Slice(res[3:6,3:6].flatten().tolist())
                and Slice(res[3:6,6:9].flatten().tolist())

            )

代码中使用了一部分numpy的函数,其实完全没必要用,普通的方法也可以实现。就是顺便复习一下numpy。
关于numpy的总结,可以看我另一篇文章,有总结笔记。

法二:(哈希表套列表)

我也是才知道哈希表可以这样套用。
哈希表套用 定义方法:

from collections import  defaultdict

        xx = defaultdict(list)  # 哈希表套list
        xy = defaultdict(set)   #`哈希表套set
        						# 其他套法同理 

假设 三个哈希表 row 存行 col 存列 nin 存九宫格

实际上我们平常用的哈希表是这样的 {key:val}。而哈希表套列表,就是将val出变成一个列表 {key:[list]}
像这道题 我们就可以用key表示行数(列数,九宫格) .而val可以表示该行、列、九宫格里的数字 ,
比如 row = {0:[1,3,4,5]} 表示第0行 里有数字 1,3,4,5

且,每个数字必定存在于 某个行、某个列、某个九宫格当中,
可以使用 公式 : i // 3 * 3 + j // 3 计算当前数字在那个九宫格之中。

所以有了以下算法步骤。

  • 遍历整体数组,看当前元素是否在行、列、九宫格之中,如果在,则检查是否有重复的,有重复则直接返回False。如果不在则加入其中。(此时行,列,九宫格,三个哈希表均需加入,原因前面已经说过了。)

  • 若当前元素为空 即题中所给的 逗号,则直接结束本次循环。

完整代码

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        from collections import  defaultdict

        row = defaultdict(list) # 行
        col = defaultdict(list) # 列
        nin = defaultdict(list) # 九宫格
        for i in range(9):
            for j in range(9):
                val = board[i][j]
                if val == '.':
                    continue

                point = i // 3 * 3 + j // 3

                if val in row[i] or val in col[j] or val in nin[point]:
                    return False
                row[i].append(val)
                col[j].append(val)
                nin[point].append(val)
                
        return  True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度不学习!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值