力扣第三十七题——解数独

news2024/9/17 4:03:37

内容介绍

编写一个程序,通过填充空格来解决数独问题。

数独的解法需 遵循如下规则

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

数独部分空格内已填入了数字,空白格用 '.' 表示。

示例 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"]]
输出:[["5","3","4","6","7","8","9","1","2"],["6","7","2","1","9","5","3","4","8"],["1","9","8","3","4","2","5","6","7"],["8","5","9","7","6","1","4","2","3"],["4","2","6","8","5","3","7","9","1"],["7","1","3","9","2","4","8","5","6"],["9","6","1","5","3","7","2","8","4"],["2","8","7","4","1","9","6","3","5"],["3","4","5","2","8","6","1","7","9"]]
解释:输入的数独如上图所示,唯一有效的解决方案如下所示:


提示:

  • board.length == 9
  • board[i].length == 9
  • board[i][j] 是一位数字或者 '.'
  • 题目数据 保证 输入数独仅有一个解

完整代码

 bool line[9][9];
bool column[9][9];
bool block[3][3][9];
bool valid;
int* spaces[81];
int spacesSize;

void dfs(char** board, int pos) {
    if (pos == spacesSize) {
        valid = true;
        return;
    }

    int i = spaces[pos][0], j = spaces[pos][1];
    for (int digit = 0; digit < 9 && !valid; ++digit) {
        if (!line[i][digit] && !column[j][digit] && !block[i / 3][j / 3][digit]) {
            line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = true;
            board[i][j] = digit + '0' + 1;
            dfs(board, pos + 1);
            line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = false;
        }
    }
}

void solveSudoku(char** board, int boardSize, int* boardColSize) {
    memset(line, false, sizeof(line));
    memset(column, false, sizeof(column));
    memset(block, false, sizeof(block));
    valid = false;
    spacesSize = 0;

    for (int i = 0; i < 9; ++i) {
        for (int j = 0; j < 9; ++j) {
            if (board[i][j] == '.') {
                spaces[spacesSize] = malloc(sizeof(int) * 2);
                spaces[spacesSize][0] = i;
                spaces[spacesSize++][1] = j;
            } else {
                int digit = board[i][j] - '0' - 1;
                line[i][digit] = column[j][digit] = block[i / 3][j / 3][digit] = true;
            }
        }
    }

    dfs(board, 0);
}

思路详解

方法概述

  • solveSudoku:主方法,初始化数据结构并调用DFS方法来填充数独板。
  • dfs:递归方法,用于尝试填充数独板的每个空格。

数据结构

  • line:一个二维布尔数组,用于标记每行中每个数字是否已经被使用。
  • column:一个二维布尔数组,用于标记每列中每个数字是否已经被使用。
  • block:一个三维布尔数组,用于标记每个3x3宫格中每个数字是否已经被使用。
  • valid:一个布尔变量,用于标记是否已经找到有效的数独解决方案。
  • spaces:一个指针数组,用于存储所有空格的位置。
  • spacesSize:一个整数,用于记录空格的数量。

解题步骤

初始化
  1. 使用memset函数将linecolumnblock数组初始化为false,表示所有数字都未被使用。
  2. valid变量设置为false,表示尚未找到解决方案。
  3. 遍历数独板,对于每个元素:
    • 如果是空格(即’.'),则记录该空格的位置到spaces数组,并增加spacesSize
    • 如果是非空格,则更新linecolumnblock数组,标记该数字已被使用。
深度优先搜索(DFS)
  1. 递归方法dfs接收当前填充空格的位置pos
  2. 如果pos等于spacesSize,说明所有空格都已填充,设置validtrue并返回。
  3. 对于当前空格位置,尝试填充数字1到9:
    • 检查当前数字是否在当前行、当前列和当前3x3宫格中未被使用。
    • 如果未被使用,则更新linecolumnblock数组,将当前数字标记为已使用,并在数独板上填充该数字。
    • 递归调用dfs,尝试填充下一个空格。
    • 如果递归调用后未找到解决方案,则回溯,撤销当前数字的填充,并继续尝试下一个数字。
解决方案
  • 如果在DFS过程中找到了有效的解决方案,valid将被设置为true,数独板将被填充完成。
  • 如果所有可能的填充方式都尝试过后仍未找到解决方案,则数独无解。

总结

这段代码通过深度优先搜索算法和回溯策略来解决问题。它通过递归地尝试填充每个空格,并在每一步都检查是否违反了数独的规则,从而找到有效的解决方案。通过使用布尔数组来跟踪每个数字的使用情况,代码能够高效地进行检查和回溯。

知识点精炼

  1. 深度优先搜索(DFS)

    • 使用递归方法实现DFS,探索数独所有可能的填充组合。
  2. 回溯算法

    • 在DFS中应用回溯,撤销之前的填充以探索新的可能性。
  3. 布尔数组

    • 使用布尔数组linecolumnblock来跟踪每个数字在行、列和宫格中的使用情况。
  4. 数独规则

    • 确保每行、每列和每个3x3宫格内的数字1至9不重复。
  5. 数组初始化

    • 使用memset函数初始化布尔数组,确保所有值初始为false
  6. 动态内存分配

    • 使用mallocspaces数组分配内存,存储空格位置。
  7. ASCII转换

    • 通过字符与整数的ASCII转换,实现字符数字与整数的相互转换。
  8. 索引计算

    • 使用数组索引来访问和更新行、列和宫格的状态。
  9. 递归终止条件

    • 当所有空格都被填充时,递归终止,并标记找到有效解决方案。
  10. 状态重置

    • 在回溯过程中,撤销对行、列和宫格状态的更改,以便探索其他可能的填充。
  11. 全局变量

    • 使用全局变量valid来标记是否找到解决方案,以及spacesSize来跟踪空格数量。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1952449.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《破解验证码:用Requests和Selenium实现模拟登录的终极指南》

两种模拟登录方式(图形验证码) 超级鹰 打码平台&#xff0c;用于识别验证码 requests模拟登录 from chaojiying import Chaojiying_Client import requests from requests import Session from lxml import etree #获取图片信息 def get_pic_info(img_name):chaojiying Ch…

贪心算法总结(2)

一、买卖股票的最佳时机 . - 力扣&#xff08;LeetCode&#xff09; class Solution { public:int maxProfit(vector<int>& prices) {int miniINT_MAX;int ret0;for(int&price:prices){//遍历的时候&#xff0c;我们随时去更新最小的值&#xff0c;然后让每一位…

AI音乐大模型背后的技术突破、版权诉讼和资本蛋糕

音乐&#xff0c;对你来说&#xff0c;是什么&#xff1f; 音乐对于我们中的许多人来说&#xff0c;是生活中不可或缺的一部分。它不仅仅是娱乐&#xff0c;更是一种情感的表达和交流方式。音乐是一种语言&#xff0c;可以用来表达感受&#xff0c;描绘作曲家想要传达的某种情…

fatal: refusing to merge unrelated histories

出现本地仓库和远程仓库的代码合并不兼容问题&#xff0c;解决方法&#xff1a; 添加--allow-unrelated-histories&#xff0c;让git允许提交不关联的历史代码。 成功提交&#xff1a;

云计算概念以及与云服务的区别

1.云的概念 1.1 什么是云&#xff1f; “云”在计算机科学和信息技术领域通常指“云计算”&#xff0c;即通过互联网提供计算资源&#xff08;如服务器、存储、数据库、网络、软件、分析等&#xff09;的模式。用户可以按需访问和使用这些资源&#xff0c;而无需管理和维护实际…

抓包工具——wireshark的使用

​ 什么是wireshark wireshark是一个数据包捕捉程序。和linux下的tcpdump&#xff0c;以及sniffer&#xff0c;Fidder等软件功能类似。按理说&#xff0c;我们的计算机中的网卡设备只会将发给本机的数据包传输到上层进行解析&#xff0c;而其他的数据包会进行丢弃&#xff0c;…

Bert文本分类和命名实体的模型架构剖析

文章目录 介绍Bert模型架构损失计算方式BertForSequenceClassificationBertForTokenClassification Bert 输出结果剖析例子 参考资料 介绍 文本分类&#xff1a;给一句文本分类&#xff1b; 实体识别&#xff1a;从一句文本中&#xff0c;识别出其中的实体&#xff1b; 做命名…

万界星空科技灯具行业MES系统:点亮生产管理的未来

在快速迭代的灯具行业中&#xff0c;高效、精准的生产管理是企业保持竞争力的关键。万界星空科技推出的灯具行业MES&#xff08;制造执行系统&#xff09;系统&#xff0c;以其强大的功能和完善的管理体系&#xff0c;正成为众多灯具生产企业的首选解决方案。本文将重点介绍万界…

构建高并发Web服务:Gunicorn与Flask在Docker中的完美融合

1. 引言 在数字化时代&#xff0c;Web服务的性能和可靠性对于任何在线业务的成功至关重要。随着用户基数的增长和业务需求的扩展&#xff0c;高并发处理能力成为了衡量一个Web服务质量的关键指标。高并发Web服务不仅能够确保用户体验的流畅性&#xff0c;还能在流量激增时保持…

抖音矩阵管理系统开发:全面解析与推荐

在数字时代&#xff0c;短视频平台如抖音已经成为人们生活中不可或缺的一部分。随着内容创作者数量的激增&#xff0c;如何高效地管理多个抖音账号&#xff0c;实现内容矩阵化运营&#xff0c;成为了众多创作者关注的焦点。今天&#xff0c;我们就来全面解析抖音矩阵管理系统的…

Android 生成Excel并导出全流程

前言 最近接到需求&#xff0c;要在安卓上离线完成根据数据生成Excel文件&#xff0c;但搜到了都不是能立马使用 例如 // implementation org.apache.poi:poi:3.17 // implementation com.alibaba:easyexcel:4.0.1 这两最大的问题是专用于java的&#xff0c;如果And…

【SpringBoot】7 数据库(MySQLMyBatis)

MySQL 前提&#xff1a;本地有安装 MySQL 。 连接 使用工具 Navicat Premium &#xff0c;或者 IDEA 自带的 DB 工具&#xff0c;或者其他能连接 MySQL 数据库的工具都可以。 1&#xff09;创建 MySQL Data Source 2&#xff09;根据本地配置连接上 MySQL&#xff0c;点击…

移动UI:排行榜单页面如何设计,从这五点入手,附示例。

移动UI的排行榜单页面设计需要考虑以下几个方面&#xff1a; 1. 页面布局&#xff1a; 排行榜单页面的布局应该清晰明了&#xff0c;可以采用列表的形式展示排行榜内容&#xff0c;同时考虑到移动设备的屏幕大小&#xff0c;应该设计合理的滚动和分页机制&#xff0c;确保用户…

Android 软键盘挡住输入框

Android原生输入法软键盘挡住输入框,网上各种解法,但不起效。 输入框都是被挡住了,第二张图的小点,实际就是输入法的光标。 解法: packages\inputmethods\LatinIME\java\res\values-land config.xml <!-- <fraction name="config_min_keyboard_height"&g…

2024年国际高校数学建模大赛(IMMCHE)问题A:金字塔石的运输成品文章分享(仅供学习)

2024 International Mathematics Molding Contest for Higher Education Problem A: Transportation of Pyramid Stones&#xff08;2024年国际高校数学建模大赛&#xff08;IMMCHE&#xff09;问题A&#xff1a;金字塔石的运输&#xff09; 古埃及金字塔石材运输优化模型研究…

【单片机毕业设计选题24084】-基于嵌入式的16位AD采集系统设计

系统功能: 系统上电后显示“欢迎使用数模转换系统请稍后”后两秒后进入正常显示。 第一行显示ADS1115第一通道采集到的电压值 第二行显示ADS1115第二通道采集到的电压值 第一行显示ADS1115第三通道采集到的电压值 第二行显示ADS1115第四通道采集到的电压值 手动调节四个电…

【产品应用】一体化伺服电机在AGV小车中的应用

随着自动化技术的快速发展&#xff0c;自动引导车&#xff08;AGV&#xff0c;Automated Guided Vehicle&#xff09;在物流、仓储和生产等领域的应用日益广泛。 作为智能物流体系中的重要设备&#xff0c;AGV小车通过先进的控制技术、传感器技术和导航系统&#xff0c;实现了…

潜水通信定位系统的功能概述_鼎跃安全

水域救援是一项极具挑战性的救援行动&#xff0c;其特点鲜明&#xff0c;集突发性、时间敏感性、技术精密性、难度系数高及潜在危险性之大成。这类救援任务往往要求在极短的时间内迅速响应&#xff0c;面对复杂多变的水域环境&#xff0c;救援人员必须具备高超的专业技能和冷静…

23万一张的天价卡牌,如何撑起一个港股IPO?

23万&#xff0c;可以买到什么&#xff1f; 是拿下一辆涨价后的宝马i3&#xff1f;还是在三线城市全款盘下一套房&#xff1f;又或是来一次环球旅行&#xff1f;这些都已经过时了&#xff0c;对于现在的年轻人来说&#xff0c;他们或许会选择拿这些钱去二手市场&#xff0c;收…

pycharm关闭项目时,页面卡住了,怎么办?

问题 在关闭pycharm时&#xff0c;有时会遇到卡在退出进度条的界面&#xff0c;很讨厌&#xff0c;那我们要怎么办才能退出呢&#xff1f; 说明&#xff1a;本篇文章不是从根源上解决这个问题&#xff0c;无法避免这种情况。 解决方法 方法一&#xff1a; 在卡住时&#xf…