题目在这: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