当前位置: 首页 > article >正文

有效的数独(C语言解法)

力扣第36题:有效的数独(C语言解法)

题目描述

判断一个 9x9 的数独是否有效。只需要根据以下规则验证:

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 子数独中只能出现一次。

注意:

  • 数独部分空白的格子用 '.' 表示。
  • 一个有效的数独(部分填充)不一定是可解的。
  • 数组中的字符只能是 1-9'.'

示例

输入:
[
  ["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

解题思路

我们可以用三个布尔二维数组来记录数字是否在行、列或 3x3 子方块中出现过:

  1. rows[9][9]:记录每行是否出现过某个数字。
  2. cols[9][9]:记录每列是否出现过某个数字。
  3. boxes[9][9]:记录每个 3x3 子方块是否出现过某个数字。

对于每个数字,确定它属于哪个 3x3 子方块可以通过以下公式:

  • 子方块索引为 (i / 3) * 3 + j / 3,其中 i 是行索引,j 是列索引。

如果在遍历过程中,某个数字已经出现在对应的行、列或子方块中,则说明数独无效,返回 false。否则,将该数字标记为已出现。

C语言代码实现

#include <stdbool.h>

bool isValidSudoku(char board[9][9]) {
    bool rows[9][9] = {false};
    bool cols[9][9] = {false};
    bool boxes[9][9] = {false};
    
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (board[i][j] != '.') {
                int num = board[i][j] - '1';  // 将字符数字转为0-8的整数
                int boxIndex = (i / 3) * 3 + j / 3;
                
                // 检查是否在行、列或子方块中已出现过
                if (rows[i][num] || cols[j][num] || boxes[boxIndex][num]) {
                    return false;  // 若已出现则无效
                }
                
                // 标记行、列和子方块中该数字已出现
                rows[i][num] = true;
                cols[j][num] = true;
                boxes[boxIndex][num] = true;
            }
        }
    }
    return true;
}

int main() {
    char board[9][9] = {
        {'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'}
    };
    
    if (isValidSudoku(board)) {
        printf("有效的数独\n");
    } else {
        printf("无效的数独\n");
    }
    
    return 0;
}

代码解析

1. 初始化布尔数组

定义 rows[9][9]cols[9][9]boxes[9][9] 三个二维布尔数组,用于标记数独的每一行、每一列和每个 3x3 子方块中数字 1-9 是否已经出现。

bool rows[9][9] = {false};
bool cols[9][9] = {false};
bool boxes[9][9] = {false};
2. 遍历数独表格

使用双重循环遍历每一个格子,i 表示行,j 表示列。

for (int i = 0; i < 9; i++) {
    for (int j = 0; j < 9; j++) {
        ...
    }
}
3. 跳过空格

如果 board[i][j]'.',说明当前格子为空,直接跳过。

if (board[i][j] != '.') {
    ...
}
4. 计算数字和 3x3 子方块索引

将当前字符数字 board[i][j] 转换为整数索引 num,并计算其所在的 3x3 子方块索引 boxIndex

int num = board[i][j] - '1';  // 将字符数字转为0-8的整数
int boxIndex = (i / 3) * 3 + j / 3;
5. 检查是否有重复

检查 rows[i][num]cols[j][num]boxes[boxIndex][num] 是否已经为 true,若为 true,则返回 false,表示数独无效。

if (rows[i][num] || cols[j][num] || boxes[boxIndex][num]) {
    return false;
}
6. 标记已出现

如果未重复,将 rows[i][num]cols[j][num]boxes[boxIndex][num] 标记为 true,表示该数字已在当前行、列或 3x3 子方块中出现。

rows[i][num] = true;
cols[j][num] = true;
boxes[boxIndex][num] = true;
7. 返回结果

遍历结束后,如果没有发现冲突,则返回 true

时间复杂度

由于数独表格大小固定为 9 × 9 9 \times 9 9×9,即 81 个格子,因此算法时间复杂度为 O ( 1 ) O(1) O(1),对每个格子判断只需常数时间。


http://www.kler.cn/a/379340.html

相关文章:

  • EHOME视频平台EasyCVR萤石设备视频接入平台视频诊断技术可以识别哪些视频质量问题?
  • html简易流程图
  • 软件架构演变:从单体架构到LLM链式调用
  • unocss 添加支持使用本地 svg 预设图标,并支持更改大小
  • Maven随笔
  • 基于Spring Boot的中小型制造企业质量管理系统设计与实现,LW+源码+讲解
  • Kubernetes中的cm存储
  • Docker入门系列——网络
  • Python 中不能正确输出两个浮点数乘积的解决方法
  • 回溯2:深入探讨C语言中的操作符 —— 从基础到进阶
  • Spring中lazy-init属性
  • 大模型日报|10 篇必读的大模型论文
  • 【eNSP】企业网络架构实验
  • 监听el-table中 自定义封装的某个组件的值发现改变调用函数
  • P11118 [ROI 2024 Day 2] 无人机比赛 题解
  • 代码随想录算法训练营第十七天|235. 二叉搜索树的最近公共祖先、701.二叉搜索树中的插入操作、450.删除二叉搜索树中的节点
  • 木马病毒相关知识
  • 什么是 Pump.fun?
  • 代码随想录day20 二叉树(七)
  • ==,===,Object.is的区别
  • 春日启航:海滨学院班级记忆的数字化之旅
  • shell脚本案例:创建用户和组
  • SpringBoot抗疫物资管理系统:技术架构解析
  • 使用 async/await 时未捕获异常的问题及解决方案
  • spark集群模式-standalone的配置和使用
  • EJEAS S2滑雪对讲机全球发布会圆满举办,为滑雪市场注入新活力