算法系列之回溯算法求解数独及所有可能解
有没有对数独感兴趣的朋友呢?数独作为一款经典的逻辑游戏,其目标是在一个9x9的方格中填入数字1至9,确保每一行、每一列以及每一个3x3的子网格中都包含这些数字且不重复。尽管数独的规则看似简单,但编写一个能够自动求解数独的程序却是一项颇具挑战性的任务。本文将深入探讨如何运用回溯算法来实现数独的自动求解。
数独求解算法及步骤
我们使用一个二维数组来表示数独的表格,空位置填充0。
数独求解的核心算法是回溯算法。回溯算法是一种通过逐步构建解决方案并在遇到冲突时回退的算法。具体来说,我们尝试在空格中填入一个数字,然后递归地继续填充下一个空格。如果在某个步骤中发现无法继续填充,则回退到上一步并尝试其他数字。
- 算法步骤
-
寻找空格:我们循环数独的所有单元格,如果数组的值为0的话则此格未填写数字。
-
尝试填入数字:对于这个空格,尝试填入1到9中的一个数字。
-
检查数字的正确性:检查填入的数字是否与当前行、列和3x3子网格中的数字有重复。
-
递归求解:如果没有重复,则递归地继续填充下一个空格。
-
回溯:如果在某个步骤中发现无法继续填充,则回退到上一步并尝试其他数字。
Java代码实现
我们使用一个二维数组来表示数独,有一种只求解数独的方法及求解不是唯一解的所有可行解的方法。代码如下
/*** 数独求解*/
public class SudokuSolver {/*** 检查数独元素的正确性,及每行、每列、每九宫格的唯一性*/public static boolean checkValue(int[][] sudoku,int value,int row,int col){//检验当前元素所在行for (int i = 0; i < 9; i++) {if(sudoku[row][i] == value){return false;}}//检验当前元素所在列for (int i = 0; i < 9; i++) {if(sudoku[i][col] == value){return false;}}//检验当前元素所在九宫格for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {// 如果当前元素所在九宫格有值,则返回falseif(sudoku[row/3*3+i][col/3*3+j] == value){return false;}}}return true;};/*** 回溯算法求解数独*/public static boolean solveSudokuSingleSec(int[][] sudoku) {//递归回溯法求解数独,循环遍历81个元素,如果当前元素为0,则尝试1-9的值,如果符合要求,则递归求解,否则返回上一层继续尝试for (int i = 0; i < 9; i++) {for(int j = 0; j < 9; j++){//如果当前元素为0,则尝试1-9的值,如果符合要求,则递归求解,否则返回上一层继续尝试if(sudoku[i][j]== 0){for (int k =1;k<=9;k++){//如果符合要求,则递归求解,否则返回上一层继续尝试if(checkValue(sudoku,k,i,j)){sudoku[i][j] = k;if(solveSudokuSingleSec(sudoku)){return true;}// 回溯sudoku[i][j] = 0;}}// 无法继续填充,则回退到上一步并尝试其他数字。return false;}}}// 找到一个解,则返回true,无需继续回溯return true;}/***回溯算法求解数独的所有可能解*/public static void solveSudokuSec(int[][] sudoku, List<int[][]> result) {// 递归回溯法求解数独,循环遍历81个元素,如果当前元素为0,则尝试1-9的值,如果符合要求,则递归求解,否则返回上一层继续尝试for (int i = 0; i < 9; i++) {for(int j = 0; j < 9; j++){if(sudoku[i][j]== 0){for (int k =1;k<=9;k++){if(checkValue(sudoku,k,i,j)){sudoku[i][j] = k;// 递归求解solveSudokuSec(sudoku,result);// 回溯sudoku[i][j] = 0;}}// 无法继续填充,则回退到上一步并尝试其他数字。return;}}}// 找到一个解,记录并添加到集合中int[][] resultArray = new int[9][9];for (int row = 0; row < 9; row++) {System.arraycopy(sudoku[row], 0, resultArray[row], 0, 9);}result.add(resultArray);}public static void main(String[] args) {int[][] initArraySingle = new int[][]{{8,0,0,0,0,0,0,0,0},{0,0,3,6,0,0,0,0,0},{0,7,0,0,9,0,2,0,0},{0,5,0,0,0,7,0,0,0},{0,0,0,0,4,5,7,0,0},{0,0,0,1,0,0,0,3,0},{0,0,1,0,0,0,0,6,8},{0,0,8,5,0,0,0,1,0},{0,9,0,0,0,0,4,0,0}};int[][] initArray = new int[][]{{8,0,0,0,0,0,0,0,0},{0,0,3,6,0,0,0,0,0},{0,7,0,0,9,0,2,0,0},{0,8,0,0,0,7,0,0,0},{0,0,0,0,4,5,7,0,0},{0,0,0,1,0,0,0,3,0},{0,0,1,0,0,0,0,6,8},{0,0,8,5,0,0,0,1,0},{0,9,0,0,0,0,4,0,0}};// 回溯算法求解数独solveSudokuSingleSec(initArraySingle);for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {System.out.print(initArraySingle[i][j]+" ");}System.out.println();}List<int[][]> result = new ArrayList<>();// 回溯算法求解数独的所有可能解solveSudokuSec(initArray,result);System.out.println("共"+result.size()+"种解法");for (int i = 0; i < result.size(); i++){System.out.println("解法"+(i+1)+":");for (int j = 0; j < 9; j++) {for (int k = 0; k < 9; k++) {System.out.print(initArraySingle[j][k]+" ");}System.out.println();}};}}
求解结果如下:
8 1 2 7 5 3 6 4 9
9 4 3 6 8 2 1 7 5
6 7 5 4 9 1 2 8 3
1 5 4 2 3 7 8 9 6
3 6 9 8 4 5 7 2 1
2 8 7 1 6 9 5 3 4
5 2 1 9 7 4 3 6 8
4 3 8 5 2 6 9 1 7
7 9 6 3 1 8 4 5 2
共295种解法
解法1:
8 1 2 7 5 3 6 4 9
9 4 3 6 8 2 1 7 5
6 7 5 4 9 1 2 8 3
1 5 4 2 3 7 8 9 6
3 6 9 8 4 5 7 2 1
2 8 7 1 6 9 5 3 4
5 2 1 9 7 4 3 6 8
4 3 8 5 2 6 9 1 7
7 9 6 3 1 8 4 5 2
解法2:
8 1 2 7 5 3 6 4 9
9 4 3 6 8 2 1 7 5
6 7 5 4 9 1 2 8 3
1 5 4 2 3 7 8 9 6
3 6 9 8 4 5 7 2 1
2 8 7 1 6 9 5 3 4
5 2 1 9 7 4 3 6 8
4 3 8 5 2 6 9 1 7
7 9 6 3 1 8 4 5 2
解法3:
...
总结
通过使用回溯算法,我们可以有效地求解数独问题。虽然回溯算法在最坏情况下的时间复杂度较高,但对于标准9x9的数独问题,它通常能够在合理的时间内找到解决方案。希望本文对你理解数独求解算法有所帮助,并激发你进一步探索算法的兴趣。
相关文章:
算法系列之回溯算法求解数独及所有可能解
有没有对数独感兴趣的朋友呢?数独作为一款经典的逻辑游戏,其目标是在一个9x9的方格中填入数字1至9,确保每一行、每一列以及每一个3x3的子网格中都包含这些数字且不重复。尽管数独的规则看似简单,但编写一个能够自动求解数独的程序…...
动态路径规划——01背包问题讲解和通过滚动数组优化
如果没有动态路径规划基础的兄弟可以出去了,这个题目有两个问题 第一问讲解: 1.定义状态表示 刚开始我做的时候根据我的经验定义了一个状态表示dp[i]表示从1到i个物品中选择的最大价值,但是这个状态表示有一个明显的问题,我怎么知…...
蓝队基本技能 web入侵指南 日志分析 后门查杀 流量分析
前言 为了赶工我是没学过红队的,首先我们要做的是 1、拿到用户给的web的时候 要先知道 web的源码 服务器 中间件 数据库这些信息 2、知道web日志放在哪里 会一些基本的分析 3、webshell查杀的基本技能 4、会分析基本的工具链 会写报告 .NET IIS 配置…...
docker基本应用和相关指令
文章目录 概要镜像管理容器操作网络管理数据卷管理其他常用指令典型场景示例小结 概要 Docker的命令通常分为几个大类,比如镜像管理(images)、容器管理(containers)、网络(network)、数据卷&…...
Django REST Framework中的序列化器类和视图类
序列化器类 一、Serializer序列化类 Serializer是DRF的序列化器基类,提供基本功能,使用Serializer类需要自己定义字段名称和类型。 BookSerializer(Serializer):name serializers.CharField()price serlializers.IntegerField()date serlializers.…...
模拟人生4大型MOD整合包3000+
存档介绍 (懒人萌新必备) 游戏内全面的人物美化、房屋改造、地图美化 美化人物250个(颜值在线,均搭配八套服饰) 全地图房屋改造(住宅、公寓、公用/商业地段等) 游戏内22张地图均已美化替换 存档…...
算法基础 -- Brian Kernighan 算法初识
Brian Kernighan 算法:利用 x & (x - 1) 逐步清除最低位的 1 1. 算法原理 x & (x - 1) 这个操作的作用是每次清除 x 的最低位的 1。由于 二进制的减法 会影响最低的 1,我们可以利用这一特性不断去除 1,直到 x 变为 0,从…...
基于Uniapp开发tab选项卡/标签栏前端组件
在开发一些业务场景时候,可能需要切换标签栏来展示不同的信息列表。 为此开发了一个Uniapp组件(myTab),下面为组件的展示效果: 案例代码: <template><view class"content"><myt…...
双向广搜
从两侧同时展开,那测数据少就从哪侧展,两者展开结果出现一样的,返回答案 127. 单词接龙 - 力扣(LeetCode) class Solution { public:int ladderLength(string beginWord, string endWord, vector<string>& wordList) {unordered_set<stri…...
2024下半年真题 系统架构设计师 论文写作 答案解析
系统架构设计师第二版VIP课程https://edu.csdn.net/course/detail/40283 试题一 论软件维护及其应用 请围绕“论软件维护及其应用”论题,依次从以下三个方面进行论述。 1.概要叙述你参与分析设计的软件项目以及你在其中所承担的主要工作。 2.请介绍软件维护的内…...
【VSCODE 插件 可视化】:SVG 编辑插件 SVG Editor
插件下载 svgeditor 创建文件 Windows/Linux 快捷键 Ctrl Shift P 打开VSCODE 命令面板查找 New File With Svg Editor 编辑文件 保存文件 打开文件以继续编辑 CG 选中多个:shift单击没找到横向分布功能无法用键盘微调位置...
go中实现子模块调用main包中函数的方法
你提到的“import cycle not allowed”错误是 Go 语言中一个常见的问题,表示在包的导入中存在循环依赖。在 Go 中,一个包不能直接或间接导入自己,否则就会报这个错误。 在你提到的第二个例子中,main 包和 submodule 包相互导入&a…...
VUE的脚手架搭建引入类库
VUE的小白脚手架搭建 真的好久好久自己没有发布自己博客了,对于一直在做后端开发的我 ,由于社会卷啊卷只好学习下怎么搭建前端,一起学习成长吧~哈哈哈(最终目的,能够懂并简易开发) 文章目录 VUE的小白脚手架搭建1.下载node.js2.安装vue脚手架3.创建一个项目4.代码规范约束配置(…...
java maven依赖传递以及版本冲突
文章目录 基本背景基本排查冲突工具依赖传递:很多依赖到底使用哪个版本的依赖dependencyManagement 作用exclusions其他问题 基本背景 你使用 java,使用 maven pom.xml 管理你的依赖包 可能常常遇到依赖版本冲突,或者很多依赖包,…...
【3-14 STC-pair超级详细的解说】
1. pair的定义和结构 • 基础概念:考察对std::pair模板类的理解,包括其头文件(<utility>)和基本语法(pair<T1, T2>)。 • 成员访问:测试对first和second成员变量的使用能力。 • 构…...
Python开发合并多个PDF文件
前言 在我们的工作中,可能有以下场景需要用到合并多个PDF: 文档归档:在企业或组织中,常常需要将相关的文档(如合同、报告、发票等)合并为一个PDF文件,以便于归档和管理。 报告生成:在…...
基于SpringBoot + Vue 的房屋租赁系统
基于springboot的房屋租赁管理系统-带万字文档 SpringBootVue房屋租赁管理系统 送文档 本项目有前台和后台两部分、多角色模块、不同角色权限不一样 共分三种角色:用户、管理员、房东 管理员:个人中心、房屋类型管理、房屋信息管理、预约看房管理、合…...
Qt QML实现弹球消砖块小游戏
前言 弹球消砖块游戏想必大家都玩过,很简单的小游戏,通过移动挡板反弹下落的小球,然后撞击砖块将其消除。本文使用QML来简单实现这个小游戏。 效果图: 正文 代码目录结构如下: 首先是小球部分,逻辑比较麻…...
ROS实践(四)机器人SLAM建图(gmapping)
目录 一、SLAM技术 二、常用工具和传感器 三、相关功能包 1. gmapping建图功能包 2. map_server 四、SLAM 建图实验 1. 配置gmapping(launch文件) 2. 启动机器人仿真(含机器人以及传感器) 3. 运行gmapping节点 4. 启动rviz可视化工具 5. 保存地图文件 一、SLAM技…...
使用Arduino、ESP8266和GPS在Google地图上追踪车辆
使用 ESP8266、GPS 和 Google 地图的 Arduino Vehicle Tracker 如今,车辆跟踪系统变得非常重要,尤其是在车辆被盗的情况下。如果您的车辆安装了 GPS 系统,您可以跟踪您的车辆位置,它可以帮助警方追踪被盗车辆。 在这里,我们正在构建更高级版本的车辆跟踪系统,您可以在其…...
python数据分析文件夹篇--pandas,openpyxl,xlwings三种方法批量创建、 复制、删除工作表
前言 之前我们学习了使用pandas灵活地读取数据,包括读取工作簿中一个或几个工作表,读取工作表中一行或多行,一列或多列数据,还学习了如何将数据灵活保存到本地。 今天我们学习一下文件夹中文件的批量处理操作,包括批量…...
MyBatis 的一级、二级缓存
文章目录 1️⃣ 一级缓存(Local Cache)📌 定义🚀 示例代码 2️⃣ 二级缓存(Global Cache)📌 定义🚀 使用方式 3️⃣ 一级缓存 vs. 二级缓存 📊4️⃣ 数据共享问题&#x…...
掌握市场先机:9款销售渠道管理工具深度测评
本文主要介绍了以下9款销售渠道管理工具:1.纷享销客; 2.销帮帮; 3.小满CRM; 4.有赞; 5.Oracle NetSuite; 6.Salesforce Sales Cloud; 7.Cin7; 8.Pipedrive; 9.BigCommerc…...
【计算机网络通信 MQTT和AMQP的原理及应用场景、优缺点】
MQTT(Message Queuing Telemetry Transport)和AMQP(Advanced Message Queuing Protocol)都是常用的消息中间件协议,以下是它们的原理、应用场景、优缺点介绍: 原理 MQTT 基于发布/订阅模式,有…...
如何搭建一个适配微信小程序,h5,app的uni-app项目
在vscode搭建 uni-app 项目(Vue 3 Vite Pinia uView Plus) 一、环境准备 1. 安装 Node.js 确保已安装 Node.js(需≥14版本),可通过以下命令检查版本: node -v2. 安装 VSCode 从 VSCode 官网 下载并…...
3.14学习总结 排序算法
插入排序: 1.直接插入排序 维护一个有序区,把元素一个个插入有序区的适当位置,直到所有元素都有序为止。 for (int i 0;i < n - 1;i) {//升序int end i;int temp k[end 1];while (end > 0) {if (temp < k[end]) {k[end 1] …...
模拟类似 DeepSeek 的对话
以下是一个完整的 JavaScript 数据流式获取实现方案,模拟类似 DeepSeek 的对话式逐段返回效果。包含前端实现、后端模拟和详细注释: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…...
实用小工具——快速获取数据库时间写法
最近我遇到了一个比较棘手的问题:在工作中,各个项目所使用的数据库类型各不相同。这导致我习惯性地使用Oracle的SQL语句进行编写,但每次完成后都会遇到报错,最终才意识到项目的数据库并非Oracle。为了避免这种情况,我需…...
完善机器人:让 DeepSeek 使用Vue Element UI快速搭建 AI 交互页面
在前两篇文章中,我们已经使用 AI 生成了 Java API,并创建了一个简单的 HTML JavaScript 网页,让用户可以与 AI 机器人聊天。但如果我们想要一个更美观、更专业的交互界面,该怎么办呢?🤔 本篇文章…...
PC端QT实现mqtt客户端发布和订阅
在Windows11-64位系统下使用QT开发桌面应用程序,实现mqtt客户端的发布和订阅功能。 需求: mqtt代理服务器 --mosquitto; mqtt客户端工具 -- mqtt.fx; qtcreator开发工具 -- qtcreator6.8.2版本; 过程:…...
蓝桥云客 挖矿
0挖矿 - 蓝桥云课 问题描述 小蓝正在数轴上挖矿,数轴上一共有 n 个矿洞,第 i 个矿洞的坐标为 ai。小蓝从 0 出发,每次可以向左或向右移动 1 的距离,当路过一个矿洞时,就会进行挖矿作业,获得 1 单位矿石&…...
React开发指南:核心、实践与案例
文章目录 一、React核心架构与设计哲学1.1 虚拟DOM与Diff算法1.2 JSX编译原理1.3 组件化设计模式1.4 Fiber架构解析1.5 组件生命周期(类组件) 二、React核心特性详解2.1 数据流管理2.2 Hooks革命2.3 Context API进阶2.4 自定义Hooks设计模式 三、React 1…...
落雪音乐Pro 8.8.6 | 内置8条音源,无需手动导入,纯净无广告
洛雪音乐Pro版内置多组稳定音源接口,省去手动导入的繁琐操作,安装即可畅听海量音乐。延续原版无广告的纯净体验,支持歌单推荐与音源切换,满足个性化听歌需求。此版本仅支持在线播放,无法下载音乐,且与原版不…...
Java入职篇(1)——心态篇
Java入职篇(1)——心态篇 本人终于通过辛苦的学习以及经过大量的面试,终于拿到一份offer了!,但是的有点担心入职之后,不能胜任工作,不能安全度过试用期。在入职后能够顺利渡过刚开始最难熬的实…...
【后端】【django】Django DRF `@action` 详解:自定义 ViewSet 方法
Django DRF action 详解:自定义 ViewSet 方法 在 Django REST Framework(DRF)中,action 装饰器用于为 ViewSet 添加自定义的 API 端点。相比于 update、create 等默认方法,action 允许我们定义 更加清晰、语义化 的 A…...
【Vue.js】
一、简介 1、概述 官网GitHub - Vuejs Vue 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。 Vue.js作为一个渐进式框架,其设计理…...
SSL 和 TLS 认证
SSL(Secure Sockets Layer,安全套接层)认证是一种用于加密网络通信和验证服务器身份的安全技术。它是TLS(Transport Layer Security,传输层安全协议)的前身,虽然现在大多数应用使用的是TLS&…...
可复用表格组件设计与实现:分页、排序、筛选全功能解析
文章目录 一、组件设计思路1.1 功能需求分析1.2 技术选型 二、组件架构设计2.1 组件结构2.2 数据流设计 三、核心代码实现3.1 基础表格组件3.2 状态管理 四、功能模块实现4.1 分页组件4.2 排序控制4.3 筛选控制 五、性能优化方案5.1 虚拟滚动5.2 防抖筛选 六、完整测试方案6.1 …...
SmartFormat:轻量级文本模板库,轻松替代 string.Format
推荐一个 C# 编写的轻量级文本模板库,可以作为 string.Format 的替代品。 01 项目简介 SmartFormat不仅继承了 string.Format 的功能,还扩展了更多高级特性,例如命名占位符、列表格式化、本地化支持、复数化等。SmartFormat 提供了高性能、…...
【贪心算法4】
力扣452.用最少数量的剪引爆气球 链接: link 思路 这道题的第一想法就是如果气球重叠得越多那么用箭越少,所以先将气球按照开始坐标从小到大排序,遇到有重叠的气球,在重叠区域右边界最小值之前的区域一定需要一支箭,这道题有两…...
ES 使用geo point 查询离目标地址最近的数据
需求描述:项目中需要通过经纬度坐标查询目标地所在的行政区。 解决思路大致有种,使用es和mysql分别查询。 1、使用es进行查询 将带有经纬度坐标的省市区数据存入es中,mappings字段使用geo point类型,索引及查询dsl如下。 geo p…...
CentOS7 服务器安装 Hadoop 和 Hive
CentOS 服务器安装 Hadoop 和 Hive流程 请将以下的路径更换为自己的路径 1. 环境准备 1.1 安装 JDK Hadoop 和 Hive 需要 Java 运行环境,这里安装 OpenJDK 1.8: # 查看 Java 版本 java -version1.2 创建 Hadoop 用户(可选) …...
C语言零基础入门:嵌入式系统开发之旅
C语言零基础入门:嵌入式系统开发之旅 一、引言 嵌入式系统开发是当今科技领域中一个极具魅力和挑战性的方向。从智能家居设备到汽车电子系统,从智能穿戴设备到工业自动化控制,嵌入式系统无处不在。而C语言,作为嵌入式开发中最常…...
【数据分享】1999—2023年地级市地方一般公共预算收支状况数据(科学技术支出/教育支出等)
在之前的文章中,我们分享过基于2000-2024年《中国城市统计年鉴》整理的1999-2023年地级市的人口相关数据、染物排放和环境治理相关数据、房地产投资情况和商品房销售面积相关指标数据和社会消费品零售总额和年末金融机构存贷款余额(均可查看之前的文章获…...
直方图(信息学奥赛一本通-1115)
【题目描述】 给定一个非负整数数组,统计里面每一个数的出现次数。我们只统计到数组里最大的数。假设 Fmax(Fmax<10000)是数组里最大的数,那么我们只统计{0,1,2.....Fmax}里每个数出现的次数。 【输入】 第一行n是数组的大小。…...
基于NXP+FPGA轨道交通人机交互(HMI)和健康管理单元(PHM)解决方案
人机接口 (HMI) 是交互式显示设备,可用于司机和乘务员的交互式信息显示。也可以用于CCTV监视。满足多种接口设备连接的同时,搭载的Linux系统,可以满足客户的定制化需求。 关键特性 触摸式按键位于显示区域周围,耐用性好࿰…...
宇树与智元的崛起:机器人“灵魂”注入的技术密码
目录 机器人运动的基石:大扭矩与平衡术 大扭矩:力量的源泉 平衡术:动态平衡的艺术 从运动到智能:AI学习的“灵魂”注入 强化学习:试错中的成长 模仿学习:站在巨人的肩膀上 数据与知识共享࿱…...
TCP 全连接队列 内核层理解socket
TCP 全连接队列 理解 listen 的第二个参数 int listen(int sockfd, int backlog);backlog 参数表示 全连接队列(accept 队列)的最大长度。 那什么是全连接队列呢? 三次握手 & accept() 处理流程 客户端发送 SYN,服务器收到并…...
成功破解加密机制,研究人员解锁LinuxESXi Akira勒索软件
一位网络安全研究人员成功破解了Akira勒索软件在Linux/ESXi系统中的加密机制,使得受害者无需支付赎金即可恢复数据。 这一突破利用了勒索软件加密方法中的关键漏洞。据研究人员介绍,该恶意软件使用纳秒级的时间戳作为加密过程中的种子,这使其…...
vue2:el-table列中文字前面加icon图标的两种方式
1、文字前面加icon <el-table-column label="姓名" align="left" prop="nickName"><template #default="{ row }"><i v-if="row.sync" class="el-icon-lock"></i><span>{{ row.nic…...