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

数独系列算法

目录

一、问题背景:数独的规则与挑战

二、有效的数独:高效验证算法

问题分析

算法实现

算法复杂度

三、解数独:回溯算法的经典应用

问题分析

算法实现

算法复杂度

四、两种算法的关联与区别

五、总结


数独作为经典的逻辑谜题,不仅是休闲益智的选择,也蕴含了丰富的算法设计思路。本文将围绕 “有效的数独” 验证和 “解数独” 两个问题,深入讲解其背后的算法逻辑与实现细节。

一、问题背景:数独的规则与挑战

数独是一个 9×9 的网格,需满足以下规则:

  • 数字 1-9 在每一行只能出现一次;
  • 数字 1-9 在每一列只能出现一次;
  • 数字 1-9 在每一个 3×3 子网格(共 9 个)内只能出现一次。

我们要解决两个核心问题:

  1. 有效的数独:验证已填入的数字是否符合规则(无需保证数独可解);
  2. 解数独:填充所有空格,得到一个符合规则的完整数独。

二、有效的数独:高效验证算法

问题分析

我们需要快速判断每一行、每一列、每一个 3×3 子网格内的数字是否唯一。最直观的思路是用三个数组分别记录行、列、子网格的数字出现情况

算法实现

class Solution {
public:bool isValidSudoku(vector<vector<char>>& board) {// 三个数组分别记录:行、列、3×3子网格的数字出现情况bool rows[9][10] = {false};   // rows[i][num]:第i行是否出现过numbool cols[9][10] = {false};   // cols[j][num]:第j列是否出现过numbool grid[3][3][10] = {false};// grid[x][y][num]:第(x,y)个3×3子网格是否出现过numfor (int i = 0; i < 9; ++i) {for (int j = 0; j < 9; ++j) {if (board[i][j] == '.') continue; // 空格跳过int num = board[i][j] - '0';// 若行、列或子网格中已出现该数字,直接返回无效if (rows[i][num] || cols[j][num] || grid[i/3][j/3][num]) {return false;}// 标记该数字已出现rows[i][num] = cols[j][num] = grid[i/3][j/3][num] = true;}}return true;}
};

算法复杂度

  • 时间复杂度:O(1)(因为网格固定为 9×9,循环次数是常数);
  • 空间复杂度:O(1)(三个数组的大小固定)。

三、解数独:回溯算法的经典应用

问题分析

解数独需要填充所有空格,且每一步都要满足数独规则。这类 “尝试所有可能并回溯” 的问题,最适合用深度优先搜索(DFS)+ 回溯来解决。

算法实现

class Solution {
public:// 三个数组记录行、列、3×3子网格的数字使用情况bool row[9][10] = {false}, col[9][10] = {false}, grid[3][3][10] = {false};void solveSudoku(vector<vector<char>>& board) {// 初始化:标记已存在的数字for (int i = 0; i < 9; ++i) {for (int j = 0; j < 9; ++j) {if (board[i][j] != '.') {int num = board[i][j] - '0';row[i][num] = col[j][num] = grid[i/3][j/3][num] = true;}}}dfs(board); // 开始回溯求解}bool dfs(vector<vector<char>>& board) {// 遍历每一个格子for (int i = 0; i < 9; ++i) {for (int j = 0; j < 9; ++j) {if (board[i][j] == '.') { // 找到空格,尝试填入数字for (int num = 1; num <= 9; ++num) {// 检查该数字是否可用(行、列、子网格都未出现)if (!row[i][num] && !col[j][num] && !grid[i/3][j/3][num]) {board[i][j] = num + '0'; // 填入数字row[i][num] = col[j][num] = grid[i/3][j/3][num] = true; // 标记为已使用if (dfs(board)) { // 递归求解下一个空格,若成功则返回truereturn true;}// 回溯:撤销填入的数字,尝试下一个可能board[i][j] = '.';row[i][num] = col[j][num] = grid[i/3][j/3][num] = false;}}return false; // 所有数字都尝试过,无法填入,回溯}}}return true; // 所有空格都填满,数独已解}
};

算法复杂度

  • 时间复杂度:最坏情况下为 O(981)(每个空格有 9 种可能,共 81 个空格),但实际中由于数独规则的约束,回溯会提前剪枝,效率远高于理论上界;
  • 空间复杂度:O(1)(数组大小固定)+ 递归栈深度 O(81)(最多递归 81 层)。

四、两种算法的关联与区别

维度有效的数独解数独
目标验证已填数字是否合法填充所有空格,得到合法数独
算法核心遍历 + 哈希表(记录数字出现情况)回溯 + 剪枝(尝试所有可能并回退)
时间复杂度O(1)(固定 9×9 网格)最坏 O(981),实际远低于此
应用场景快速排查数独的合法性需得到完整解的场景

五、总结

“有效的数独” 和 “解数独” 是数独问题的两个核心方向,分别体现了哈希表验证回溯剪枝的经典算法思想。

  • 对于 “有效性验证”,利用三个数组记录行、列、子网格的数字出现情况,可在常数时间内完成判断;
  • 对于 “解数独”,回溯算法是最直接的思路,通过 “尝试 - 验证 - 回溯” 的流程,逐步填充所有空格。

这两个问题的解法也为其他类似的 “约束满足问题”(如八皇后、迷宫求解)提供了参考,掌握它们的思路,能帮助你在更多算法场景中举一反三。

http://www.dtcms.com/a/561142.html

相关文章:

  • 梅州南站电商网站建设期末考试
  • 构建一个更稳定、更聪明的 PDF 翻译 Agent:从踩坑到总结
  • 【仿RabbitMQ的发布订阅式消息队列】--- 客户端模块
  • python 初学 3 --字符串编码
  • 企网站建设比价网站怎么做的
  • Linux磁盘性能优化:文件系统选择与挂载参数调整(附案例)
  • 如何建设网站首页网站备案照
  • “RAG简单介绍
  • Spring_cloud(1)
  • 终结Linux系统崩溃——Aptitude:以搜狗输入法与fcitx/ibus依赖冲突的终极解决方案为例
  • 关于 ComfyUI 的 Windows 本地部署系统环境教程(详细讲解Windows 10/11、NVIDIA GPU、Python、PyTorch环境等)
  • 网站开发包含什么百度手机
  • 部门网站建设管理典型经验材料广东住房和城乡建设厅官方网站
  • PHP 基金会宣布:Streams 现代化 将引入事件循环与异步新能力
  • 网站建设武清wordpress 朋友圈
  • 后端八股之消息队列
  • Segment Anything: SAM SAM2
  • Oracle Linux 9 的 MySQL 8.0 完整安装与远程连接配置
  • 剑三做月饼活动网站网站制作公司司
  • 网站建设推广公司排名钓鱼链接生成器
  • 十字链表和邻接多重表
  • 中国排建设银行悦生活网站企业网站制作 深圳
  • Vue过度与动画
  • 陕西省高速建设集团公司网站商业空间设计书籍
  • 【快速入门】JMeter
  • 建立网站的基本条件免费广州网站开发维护
  • 【每天一个AI小知识】:什么是Prompt?
  • pytest核心用法
  • Linux下的简单进度条程序
  • 【ComfyUI】Stable Zero123 单图生成3D视图