[LeetCode in Python] 36 (M) valid sudoku 有效的数独

题目

https://leetcode-cn.com/problems/valid-sudoku/

判断一个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形式的。

解题思路

  • naive的思路就是分别按行、按列、按九宫格来分别验证,这样循环次数就是3个9*9。

  • 代码见下面naive version

  • 观察后发现其实可以通过集合来存储行、列、九宫格已出现过的数字,这样就只需要做一次9*9的循环即可

  • 代码见下面optimized version

  • 除此之外,还有其他优化方法,如不使用set(),改用数组,甚至使用bit来存储,都是可以的。

代码

# - naive version

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        # - check for each row
        for row in range(9):
            exist_set = set()
            for col in range(9):
                c = board[row][col]
                if c == '.': continue

                if c in exist_set:
                    return False
                else:
                    exist_set.add(c)
        
        # - check for each col
        for col in range(9):
            exist_set = set()
            for row in range(9):
                c = board[row][col]
                if c == '.': continue

                if c in exist_set:
                    return False
                else:
                    exist_set.add(c)
        
        # - check for each grid
        for gr in range(3):
            for gc in range(3):
                exist_set = set()

                for j in range(3):
                    for i in range(3):
                        c = board[gr*3 + j][gc*3 + i]
                        if c == '.': continue

                        if c in exist_set:
                            return False
                        else:
                            exist_set.add(c)
        
        return True
# - optimized version

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        row_state_list = [set() for _ in range(9)]
        col_state_list = [set() for _ in range(9)]
        grid_state_list = [set() for _ in range(9)]

        # - check for each cell
        for row in range(9):
            for col in range(9):
                c = board[row][col]
                if c == '.': continue

                grid_index = (row//3)*3 + col//3

                if c in row_state_list[row]: return False
                if c in col_state_list[col]: return False
                if c in grid_state_list[grid_index]: return False

                row_state_list[row].add(c)
                col_state_list[col].add(c)
                grid_state_list[grid_index].add(c)
        
        return True

猜你喜欢

转载自www.cnblogs.com/journeyonmyway/p/12690943.html