36. 有效的数独(Valid Sudoku)题解(C语言)

题目描述

判断一个 9×9 的数独是否有效。只需要根据以下规则验证已经填入的数字是否有效即可:

  1. 数字 1-9 在每一行只能出现一次;

  2. 数字 1-9 在每一列只能出现一次;

  3. 数字 1-9 在每一个以粗实线分隔的 3×3 宫内只能出现一次。

注意:

  • 空白格用 '.' 表示;

  • 一个有效的数独不一定是可解的,只需要验证已经填入的数字是否有效即可。

示例 1:

复制代码
输入:
board = 
[["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:

复制代码
输入:
board = 
[["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
解释:左上角 3×3 宫格内有两个 '8',因此无效。

解题思路

本题的核心是 检查三种约束条件:

  1. 每行数字不能重复;

  2. 每列数字不能重复;

  3. 每个 3×3 宫格内数字不能重复。

方法

  • 使用三个二维数组来记录数字是否出现过:

    • row[9][9]:行出现记录

    • col[9][9]:列出现记录

    • box[9][9]:3×3 宫格出现记录

  • 遍历整个棋盘:

    1. 如果当前格是 '.',跳过;

    2. 否则将字符转为数字索引 num = board[i][j] - '1';

    3. 计算当前格所属的宫格索引 boxIndex = (i / 3) * 3 + j / 3;

    4. 如果 row[i][num]、col[j][num] 或 box[boxIndex][num] 已经标记过,则返回 false;

    5. 否则将其标记为已出现。

  • 遍历完成后仍未发现冲突,则数独有效,返回 true。


C语言实现

复制代码
#include <stdbool.h>

bool isValidSudoku(char** board, int boardSize, int* boardColSize) {
    int row[9][9] = {0};
    int col[9][9] = {0};
    int box[9][9] = {0};

    for(int i = 0; i < 9; i++){
        for(int j = 0; j < 9; j++){
            if(board[i][j] == '.') continue;

            int num = board[i][j] - '1';       // 数字转换为索引 0~8
            int boxIndex = (i / 3) * 3 + j / 3; // 计算 3x3 宫格索引

            if(row[i][num] || col[j][num] || box[boxIndex][num])
                return false;

            row[i][num] = 1;
            col[j][num] = 1;
            box[boxIndex][num] = 1;
        }
    }

    return true;
}

算法分析

  • 时间复杂度:O(9×9) = O(1),固定大小棋盘,遍历每个格子一次;

  • 空间复杂度:O(9×9) = O(1),使用固定大小的三个二维数组存储状态。


总结

本题属于 经典的状态记录题,核心技巧是:

  1. 使用辅助数组记录行、列、宫格的状态;

  2. 宫格索引计算公式:boxIndex = (i/3)*3 + j/3;

  3. 遇到 '.' 跳过即可。

面试时,如果能讲出这一思路,并且写出简洁的 C 语言实现,基本可以轻松通过。


相关推荐
听风说ml7 小时前
socket编程 【C语言】
c语言·udp·tcp·socket编程
学逆向的9 小时前
C 局部静态变量
c语言·开发语言·网络安全
UIU1149 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场10 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi10 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David11 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院11 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng12 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
叉烧滑蛋14 小时前
B站台湾大学郭彦甫|MATLAB 学习笔记|04 变量与档案存取
数据结构
j7~14 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归