LeetCode 36. 有效的数独 - 解题思路与实现详解
题目描述
判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可:
- 数字 1-9 在每一行只能出现一次。
 - 数字 1-9 在每一列只能出现一次。
 - 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。
 
注意:
- 一个有效的数独(部分已被填充)不一定是可解的。
 - 只需要根据以上规则,验证已经填入的数字是否有效即可。
 - 空白格用 '.' 表示。
 
解题思路分析
1. 问题理解
数独验证的核心是检查三个维度:
- 行检查:每一行中的数字1-9不能重复
 - 列检查:每一列中的数字1-9不能重复
 - 3x3宫格检查:每个3x3的小宫格中数字1-9不能重复
 
2. 关键思考点
2.1 如何处理空白格('.')
空白格用'.'表示,在验证时需要考虑:
- 集合去重时会自动忽略'.'
 - 需要正确计算有效数字的数量
 
2.2 3x3宫格的遍历
如何正确遍历9个3x3宫格是关键:
- 每个宫格的起始位置:(0,0), (0,3), (0,6), (3,0), (3,3), (3,6), (6,0), (6,3), (6,6)
 - 使用双重循环:
for x in range(0, 9, 3): for y in range(0, 9, 3) 
2.3 列数据的提取
Python中不能直接用board[:][y]获取列,需要使用列表推导式:
            
            
              python
              
              
            
          
          column_y = [row[y] for row in board]
        代码实现
方法一:集合验证法
            
            
              python
              
              
            
          
          class Solution:
    def isValidSudoku(self, board: list[list[str]]) -> bool:
        # 检查3x3宫格
        for x in range(0, 9, 3):
            for y in range(0, 9, 3):
                # 提取当前3x3宫格的所有元素
                grids = [
                    board[x][y], board[x][y+1], board[x][y+2],
                    board[x+1][y], board[x+1][y+1], board[x+1][y+2],
                    board[x+2][y], board[x+2][y+1], board[x+2][y+2]
                ]
                # 验证:去重后的数字个数 + 空白格个数 = 9
                if (len(set(grids)) + grids.count('.')) - 1 != 9:
                    return False
        
        # 检查每一行
        for x in range(9):
            if (len(set(board[x])) + board[x].count('.')) - 1 != 9:
                return False
        
        # 检查每一列
        for y in range(9):
            column_y = [row[y] for row in board]
            if (len(set(column_y)) + column_y.count('.')) - 1 != 9:
                return False
        
        return True
        方法二:哈希表优化法
            
            
              python
              
              
            
          
          class Solution:
    def isValidSudoku(self, board: list[list[str]]) -> bool:
        # 使用哈希表记录每行、每列、每个宫格中数字的出现情况
        rows = [set() for _ in range(9)]
        cols = [set() for _ in range(9)]
        boxes = [set() for _ in range(9)]
        
        for i in range(9):
            for j in range(9):
                num = board[i][j]
                if num == '.':
                    continue
                
                # 检查行
                if num in rows[i]:
                    return False
                rows[i].add(num)
                
                # 检查列
                if num in cols[j]:
                    return False
                cols[j].add(num)
                
                # 检查3x3宫格
                box_index = (i // 3) * 3 + j // 3
                if num in boxes[box_index]:
                    return False
                boxes[box_index].add(num)
        
        return True
        关键知识点
1. Python集合操作
            
            
              python
              
              
            
          
          # 集合去重
numbers = [1, 2, 2, 3, 4, 4, 5]
unique_numbers = set(numbers)  # {1, 2, 3, 4, 5}
# 集合长度
len(unique_numbers)  # 5
        2. 列表推导式
            
            
              python
              
              
            
          
          # 提取矩阵的列
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
column_0 = [row[0] for row in matrix]  # [1, 4, 7]
column_1 = [row[1] for row in matrix]  # [2, 5, 8]
        3. 3x3宫格索引计算
            
            
              python
              
              
            
          
          # 计算(i,j)位置属于哪个3x3宫格
box_index = (i // 3) * 3 + j // 3
# 宫格编号对应关系:
# 0 1 2
# 3 4 5  
# 6 7 8
        解题过程中的常见错误
1. 错误理解集合去重
            
            
              python
              
              
            
          
          # 错误示例
grids = ['.', '1', '2', '.', '3', '4', '5', '6', '7']
unique_count = len(set(grids))  # 8 (包含了'.')
# 正确做法
valid_count = len(set(grids)) + grids.count('.') - 1  # 7
        2. 错误的列提取方式
            
            
              python
              
              
            
          
          # 错误示例
board = [[1,2,3], [4,5,6], [7,8,9]]
column = board[:][0]  # 这样不会得到第一列
# 正确做法
column = [row[0] for row in board]  # [1, 4, 7]
        3. 3x3宫格遍历错误
            
            
              python
              
              
            
          
          # 错误示例:没有在循环内重新计算grids
grids = [board[0][0], board[0][1], ...]  # 只计算了一次
for x in range(0, 9, 3):
    for y in range(0, 9, 3):
        # 应该在这里重新计算grids
        复杂度分析
时间复杂度
- 方法一:O(n²),其中n=9,需要遍历整个数独板
 - 方法二:O(n²),但实际运行更快,因为使用哈希表查找
 
空间复杂度
- 方法一:O(1),只使用常数空间
 - 方法二:O(n),需要存储行、列、宫格的哈希表
 
测试用例
            
            
              python
              
              
            
          
          # 测试用例1:有效数独
board1 = [
    ["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:无效数独(第一行有重复)
board2 = [
    ["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
        总结
这道题的核心在于:
- 理解数独规则:行、列、3x3宫格都不能有重复数字
 - 正确处理空白格:'.'不影响验证,但需要正确计算
 - 掌握Python语法:集合操作、列表推导式、矩阵操作
 - 注意边界条件:确保所有情况都被正确验证
 
通过这道题,我学会了:
- 如何验证矩阵的多个维度
 - 如何处理特殊字符(如'.')
 - 如何正确提取矩阵的行和列
 - 如何使用集合进行去重验证
 
这是一道很好的练习Python基础语法和逻辑思维的题目!
更新日期2025年8月31日