Leetcode_36【有效的数独】
文章目录:
- 题目
- 脚本一
- 脚本一逻辑
- 脚本二
- 脚本二逻辑
- shell解法分享
题目:
判断一个 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 存在, 因此这个数独是无效的。
说明:
一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
给定数独序列只包含数字 1-9 和字符 '.' 。
给定数独永远是 9x9 形式的。
脚本一:【用时:152ms】
class Solution: def isValidSudoku(self, board: List[List[str]]) -> bool: n1,n2,n3,n4 = 0,0,0,0 num1,num2 = 0,0 str2,str3,str4 = "","","" def test_str(strr): n1 = strr.count(".") n2 = len(set(strr)) if (9 - n1) != (n2 -1): return("false") else: return("true") #检查每一行 for i in range(9): n1 = board[i].count('.') n2 = len(set(board[i])) if (9 - n1) != (n2 - 1): return(False) #检查每一列 for i in range(9): str1 = "" for j in range(9): str1 += board[j][i] result = test_str(str1) if result == "false": return(False) else: pass #检查小正方形 for i in range(9): for j in range(9): if j < 3: str2 += board[i][j] elif 2 < j < 6: str3 += board[i][j] else: str4 += board[i][j] if (i+1) % 3 == 0: result1 = test_str(str2) result2 = test_str(str3) result3 = test_str(str4) if result1 == "false" or result2 == "false" or result3 == "false": return(False) else: str2 = "" str3 = "" str4 = "" return(True)
脚本一逻辑:
- 第一:如何判断行列和小正方形的数字符合数独的要求,笔者想到的是:通过行、列和小正方形变为字符串,求字符串元素个数n1,然后将字符串转变为集合,再求集合元素个数,再通过比较n1和n2的值即可知道是否符合数独要求【注意对圆点的个数处理】
- 行直接通过遍历给定列表内容即可判断
- 列表判断需要使用两个for循环才能进行遍历
- 小正方形的判断就较费心思,笔者采用的逻辑是:通过是否为3的倍数,获取3行内容,即给定列表的前三个;然后又根据列的数字将每行的元素分给不同的变量,比如123列给变量str1;456列给变量str2;789给变量str3;最后判断str1、str2、str3是否同时符合数独的要求即可
- 若遇到不符合的,返回false退出即可
脚本二:【用时:100ms】【转载】
class Solution: def isValidSudoku(self, board): """ :type board: List[List[str]] :rtype: bool """ # init data rows = [{} for i in range(9)] columns = [{} for i in range(9)] boxes = [{} for i in range(9)] # validate a board for i in range(9): for j in range(9): num = board[i][j] if num != '.': num = int(num) box_index = (i // 3 ) * 3 + j // 3 # keep the current cell value rows[i][num] = rows[i].get(num, 0) + 1 columns[j][num] = columns[j].get(num, 0) + 1 boxes[box_index][num] = boxes[box_index].get(num, 0) + 1 # check if this value has been already seen before if rows[i][num] > 1 or columns[j][num] > 1 or boxes[box_index][num] > 1: return False return True
脚本二逻辑:
- 此脚本逻辑没看懂,目测是运用了数独里面元素之间的某种关联性解决的。有兴趣的朋友可以深入研究一下
shell解法分享:
- 在笔者的CSDN博客中,之前在学习shell的时候也曾使用过shell来处理此题,以下是使用shell处理此题的链接:
- https://blog.csdn.net/weixin_43428906/article/details/102895947