返回

深入剖析 LeetCode 36:验证有效数独的艺术

闲谈

引言

LeetCode 36 题:“有效数独”,是一道经典算法问题,考验着我们对数独规则的理解和编程能力。本文将带你深入解析这道题目的本质,并用清晰的语言和生动的例子为你展现解决问题的艺术。

理解数独规则

数独是一种基于 9x9 格子的逻辑益智游戏,目标是将 1-9 的数字填充到每个格子中,满足以下规则:

  • 每行必须包含 1-9 的所有数字,且每个数字只能出现一次。
  • 每列必须包含 1-9 的所有数字,且每个数字只能出现一次。
  • 每个 3x3 宫内必须包含 1-9 的所有数字,且每个数字只能出现一次。

算法思路

为了判断一个数独是否有效,我们可以依次检查每一行、每一列和每一个宫,确保它们是否满足规则。具体算法步骤如下:

1. 行检查

遍历数独的每一行,使用一个数组记录出现过的数字。如果任何数字出现超过一次,则数独无效。

2. 列检查

类似地,遍历数独的每一列,使用一个数组记录出现过的数字。如果任何数字出现超过一次,则数独无效。

3. 宫检查

将数独划分为 9 个 3x3 宫。对于每个宫,使用一个数组记录出现过的数字。如果任何数字出现超过一次,则数独无效。

代码实现

public boolean isValidSudoku(char[][] board) {
    // 检查行
    for (int i = 0; i < 9; i++) {
        boolean[] row = new boolean[9];
        for (int j = 0; j < 9; j++) {
            int num = board[i][j] - '1';
            if (num < 0 || num >= 9 || row[num]) {
                return false;
            }
            row[num] = true;
        }
    }

    // 检查列
    for (int j = 0; j < 9; j++) {
        boolean[] col = new boolean[9];
        for (int i = 0; i < 9; i++) {
            int num = board[i][j] - '1';
            if (num < 0 || num >= 9 || col[num]) {
                return false;
            }
            col[num] = true;
        }
    }

    // 检查宫
    for (int i = 0; i < 9; i += 3) {
        for (int j = 0; j < 9; j += 3) {
            boolean[] box = new boolean[9];
            for (int k = i; k < i + 3; k++) {
                for (int l = j; l < j + 3; l++) {
                    int num = board[k][l] - '1';
                    if (num < 0 || num >= 9 || box[num]) {
                        return false;
                    }
                    box[num] = true;
                }
            }
        }
    }

    return true;
}

优化技巧

为了提高算法效率,我们可以引入一些优化技巧:

  • 使用 bitset 代替 boolean 数组来记录出现过的数字,可以大大节省空间。
  • 对输入的数独进行预处理,将每一行、每一列和每一个宫中已经填入的数字转换为对应的 bitset。
  • 并行化宫检查,使用多线程同时检查多个宫。

SEO优化