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

【算法数据结构】leetcode37 解数独


37. 解数独 - 力扣(LeetCode)

题目描述:

题目要求每一行 ,每一列,每个3*3 的子框只能出现一次。每个格子的数字范围1-9.

需要遍历每个空格填入可能的数字,并验证符合规则。如果符合就填入,不符合就回溯。

解法: 

回溯算法通常用于解决这种需要试错的问题。当发现当前路径无解时候,返回上一步重新选择。

需要遍历每个空格,找到需要填写的空格,对每个空格尝试填入1-9,检查这个数字是否满足行,列 ,子框的要求。如果满足就填入这个数字,递归进行下一个空格,如果后续处理中,发现无法填入下去,就需要回溯。恢复这个空格的状态,尝试下一个可能的数字。

检查某个数字是否可以填入当前位置

对于 位置(i,i)需要检查i 行,j 列,所在的子框是否有这个数字,属于第几个子框可以用 (i/3 )*3,(j/3 )*3来确定 。i=4   4/3=1    1*3=3    ,起始行是3 ,遍历这个3*3的子框。

对于每个空格最多检查1-9个数字。,每个数字需要检查三个方向,最坏情况可能出现重复检查。

优化方法

用哈希表或者数据记录行,列,子框。已经出现的数字。用3个二维数组,记录rowi 表示第i行是否存在数组num,colj 表示第j 列是否存在数据num,boxk 表示第k 个子框中是否存咋这个数字num,

k 可以通过  i//3*3 +j//3 来计算 

i=0 ,j=0   ,k=0

i=3,j=3 ,k=4  在第四个子框。

预处理这三个数组,遍历整个数独,对这个对每个非空的格子,将对应的行列,子框中盖数字标记为存在。比如broad_i 为5 ,那么需要row_i  设置为true ,col_j 设置为true ,box_k (k为子框的索引)设置为true。

对每个空格尝试填入1-9 数字中的一个,

初始化  9X10 数组 其中索引 0不用 

步骤

1. 预处理三个数组row、col、box,记录每个行、列、子框中已经存在的数字。

2. 收集所有需要填写的空格的位置,存入一个列表spaces。

3. 编写一个回溯函数,参数是当前处理到spaces中的第pos个位置。当pos等于spaces的长度时,说明已经填完所有空格,返回True。

4. 对于当前处理的空格位置(i,j),尝试填入1到9中的一个数字d。如果该数字满足row[i][d]、col[j][d]、box[k][d]都为False,那么将该数字填入,并更新这三个数组的状态。然后递归处理pos+1的位置。如果递归返回True,说明后续的填写都成功,那么当前的选择是正确的,直接返回True。如果递归返回False,则说明后续无法完成,需要回溯,恢复三个数组的状态,并将board[i][j]恢复为'.',然后尝试下一个数字。

5. 如果所有数字都尝试过且都不行,则返回False,触发上一层递归的回溯。

这样,当递归函数返回True时,说明已经找到解,此时board已经被正确填充。

    # 初始化 3个数组row = [[False] * 10 for i in range(9)]print(row)  # 每行十个元素col = [[False] * 10 for i in range(9)]box = [[False] * 10 for i in range(9)]

[[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, False, False, False, False],[False, False, False, False, False, False, False, False, False, False]]

 遍历数组填充已经有的数字 spaces 用于记录空格的位置

# 遍历整个数组 记录每个行 ,列子框中已经存在的数字spaces = []for i in range(9):for j in range(9):if board[i][j] != '.':d = int(board[i][j])row[i][d] = Truecol[j][d] = Truek = (i // 3) * 3 + (j // 3)box[k][d] = True  # 第k 个箱子的d 是否存在# 保存空格的位置到spaceselse:spaces.append((i, j))print("空格的位置", spaces)

空格的位置 [(0, 2), (0, 3), (0, 5), (0, 6), (0, 7), (0, 8), (1, 1), (1, 2), (1, 6), (1, 7), (1, 8), (2, 0), (2, 3), (2, 4), (2, 5), (2, 6), (2, 8), (3, 1), (3, 2), (3, 3), (3, 5), (3, 6), (3, 7), (4, 1), (4, 2), (4, 4), (4, 6), (4, 7), (5, 1), (5, 2), (5, 3), (5, 5), (5, 6), (5, 7), (6, 0), (6, 2), (6, 3), (6, 4), (6, 5), (6, 8), (7, 0), (7, 1), (7, 2), (7, 6), (7, 7), (8, 0), (8, 1), (8, 2), (8, 3), (8, 5), (8, 6)]


d = int(board[i][j])  填充的数字作为下标

  row:  row[i][d]=True

[[False, False, False, True(3), False, True(5), False, True(7), False, False],[False, True(1), False, False, False, True(5), True(6), False, False, True(9)],[False, False, False, False, False, False, True(6), False, True(8), True(9)], 
[False, False, False, True(3), False, False, True(6), False, True(8), False],[False, True(1), False, True(3), True(4), False, False, False, True(8), False],[False, False, True(2), False, False, False, True(6), True(7), False, False], 
[False, False, True(2), False, False, False, True(6), False, True(8), False],[False, True(1), False, False, True(4), True(5)), False, False, False, True(9)],[False, False, False, False, False, False, False, True(7), True(8), True(9)]]

col : col[j][d]=true   纵坐标作为 行 d作为列 

第一列   4 5  6 7 8

 [False, False, False, False, True(4), True(5), True(6), True(7), True(8), False]

[[False, False, False, False, True(4), True(5), True(6), True(7), True(8), False], 
[False, False, False, True, False, False, True, False, False, True], 
[False, False, False, False, False, False, False, False, True, False],[False, True, False, False, True, False, False, False, True, False],[False, True, True, False, False, False, True, True, True, True], 
[False, False, False, True, False, True, False, False, False, True],[False, False, True, False, False, False, False, False, False, False], 
[False, False, False, False, False, False, True, True, True, False], 
[False, True, False, True, False, True, True, False, False, True]]

   box :      k = (i // 3) * 3 + (j // 3)
                box[k][d] = True  # 第k 个箱子的d 是否存在

  例如  board[4][3]=8   k=(4//3)*3 +(3//1) =4  第4个子框  第8个标记为true

[[False, False, False, True, False, True, True, False, True, True], 
[False, True, False, False, False, True, False, True, False, True],[False, False, False, False, False, False, True, False, False, False], 
[False, False, False, False, True, False, False, True, True, False],[False, False, True, True, False, False, True, False, True(8), False], 
[False, True, False, True, False, False, True, False, False, False],[False, False, False, False, False, False, True, False, False, False],[False, True, False, False, True, False, False, False, True, True], 
[False, False, True, False, False, True, False, True, True, True]]

定义回溯

# 定义回溯def backtrack(pos):print("pos", pos)if pos == len(spaces):  # 当pos 等于spaces长度时候说明已经填写完 ,返回trueprint("结果", board)return Truei, j = spaces[pos]k = (i // 3) * 3 + (j // 3)for d in range(1, 10):  # 对这个位置尝试填充1-9if not row[i][d] and not col[j][d] and not box[k][d]:  # 满足为false 时候填入row[i][d] = Truecol[j][d] = Truebox[k][d] = Trueboard[i][j] = str(d)if backtrack(pos + 1):return True# 回溯row[i][d] = Falsecol[j][d] = Falsebox[k][d] = Falseboard[i][j] = '.'  # 恢复空格return Falsebacktrack(0)

代码 

class Solution:def solveSudoku(self, board: List[List[str]]) -> None:"""Do not return anything, modify board in-place instead."""# 初始化三个数组row=[[False] *10 for _ in range(9)]col=[[False] *10 for _ in range(9)]box=[[False] *10 for _ in range(9)]spaces=[] # 记录空格位置# 遍历数组填充已经有的数字for i in range(9):for j in range(9):if board[i][j]!='.':d=int(board[i][j])row[i][d]=Truecol[j][d]=Truek=(i//3)*3+(j//3)box[k][d]=Trueelse:spaces.append((i,j)) # 记录空格的坐标def  backtrack(pos):if pos ==len(spaces):#遍历完了所有空格return Truei,j=spaces[pos] # 取出当前位置的空格坐标k=(i//3)*3+(j//3)for d in range(1,10):  # 尝试对该位置填充1-9if row[i][d]==False and col[j][d]==False and box[k][d]==False:row[i][d]=Truecol[j][d]=Truebox[k][d]=Trueboard[i][j]=str(d)if backtrack(pos+1):return True#不满足  回溯row[i][d]=Falsecol[j][d]=Falsebox[k][d]=Falseboard[i][j]='.' return Falsebacktrack(0)

相关文章:

【算法数据结构】leetcode37 解数独

37. 解数独 - 力扣(LeetCode) 题目描述: 题目要求每一行 ,每一列,每个3*3 的子框只能出现一次。每个格子的数字范围1-9. 需要遍历每个空格填入可能的数字,并验证符合规则。如果符合就填入,不符…...

招商信诺原点安全:一体化数据安全管理解决方案荣获“鑫智奖”!

近日,“鑫智奖 2025第七届金融数据智能优秀解决方案评选”榜单发布,原点安全申报的《招商信诺:数据安全一体化管理解决方案》荣获「信息安全创新优秀解决方案」。 “鑫智奖第七届金融数据智能优秀解决方案评选”活动由金科创新社主办&#x…...

楼宇自控系统如何为现代建筑打造安全、舒适、节能方案

在科技飞速发展的当下,现代建筑对功能和品质的要求日益提升。楼宇自控系统作为建筑智能化的核心技术,宛如一位智慧的“管家”,凭借先进的技术手段,为现代建筑精心打造安全、舒适、节能的全方位解决方案,让建筑真正成为…...

吃透LangChain(四):消息管理与聊天历史存储

消息存储在内存 下面我们展示一个简单的示例,其中聊天历史保存在内存中,此处通过全局 Python 字典实现。我们构建一个名为 get_session_history 的可调用对象,引用此字典以返回chatMessageHistory实例。通过在运行时向 RunnablewithMessageHi…...

【差分隐私相关概念】瑞丽差分隐私(RDP)命题4

命题4的证明详解(分情况讨论) 背景与设定 机制: f : D → R f: \mathcal{D} \to \mathcal{R} f:D→R 是由 n n n 个 ϵ \epsilon ϵ-差分隐私机制自适应组合而成。相邻输入: D D D 和 D ′ D D′ 是相邻数据集。目标&#xf…...

RoBoflow数据集的介绍

https://public.roboflow.com/object-detection(该数据集的网址) 可以看到一些基本情况 如果我们想要下载,直接点击 点击图像可以看到一些基本情况 可以点击红色箭头所指,右边是可供选择的一些yolo模型的格式 如果你想下载…...

免费将AI生成图像放大4倍的方法

有些人不需要任何高级工具和花哨的技巧;他们只需要一种简单的方法来提升图像分辨率而不损失任何质量 — 今天,我们将学习如何做到这一点。 生成AI图像最大的问题之一是什么?最终结果通常分辨率非常低。 这会导致很多不同的问题,特别是对于那些想要在内容或项目中使用这些…...

滑动过期机制——延长 Token有效期

文章目录 1. Flask 后端代码(支持 WebSocket)2. Android Studio Java 前端代码(使用 Socket.IO)代码说明后端前端 注意事项 前端使用 Android Studio(Java)和 Socket.IO 库,后端使用 Flask。 1…...

《JVM考古现场(二十三):归零者·重启奇点的终极奥义》

目录 楔子:归零者文明觉醒 上卷十维弦理论破译 第一章:JVM弦论代码考古 第二章:超膜引用解析算法 第三章:量子真空涨落监控 中卷归零者心法实战 第四章:宇宙重启倒计时引擎 第五章:内存奇点锻造术 第…...

k8s中sidecar死循环

序言 怎么发现我的同事们很上进呢,估计做了下贱的事儿吧。 伤不到我,不代表不疼! sidecar产生的问题 1 背景 在k8s的环境中,pod的使用越来越多了,也就产生了sidecar容器,在现在的环境中,一个pod…...

Linux `init 4` 相关命令的完整使用指南

Linux init 4 相关命令的完整使用指南—目录 一、init 系统简介二、init 4 的含义与作用三、不同 Init 系统下的 init 4 行为1. SysVinit(如 CentOS 6、Debian 7)2. systemd(如 CentOS 7、Ubuntu 16.04)3. Upstart(如 …...

Java Web 之 简介 100问

DAO 层的作用是什么? DAO 层作用: 与数据库直接交互,封装所有数据访问的细节(即CRUD操作),不包含业务逻辑,只关注数据的持久化。 DAO的全拼是什么 Data Access Object,数据连接实…...

06-libVLC的视频播放器:推流RTMP

创建媒体对象 libvlc_media_t* m = libvlc_media_new_path(m_pInstance, inputPath.toStdString().c_str()); if (!m) return -1; // 创建失败返回错误 libvlc_media_new_path:根据文件路径创建媒体对象。注意:toStdString().c_str() 在Qt中可能存在临时字符串析构问题,建议…...

【物联网】基于LORA组网的远程环境监测系统设计

基于LORA组网的远程环境监测系统设计 演示视频: 简介: 1.本系统有一个主机,两个从机。 2.一主多从的LORA组网通信,主机和两个从机都配备了STM32F103单片机与 LoRa 模块,主机作为中心设备及WIFI网关,负责接收和发送数据到远程物联网平台和手机APP,两个从机则负责采集数…...

少儿编程路线规划

少儿编程路线规划—一文写明白 现在有很多的编程机构,五花八门的。我有幸也见识到了大家的营销策略。这些策略有黑有白吧,从业几年,沉淀下来一些客户角度的干货,分享给大家。 如果是想以很远很远的就业为目的,毕业就…...

第3章 垃圾收集器与内存分配策略《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》

第3章 垃圾收集器与内存分配策略 3.2 对象已死 Java世界中的所有对象实例,垃圾收集器进行回收前就是确定对象哪些是活着的,哪些已经死去。 3.2.1 引用计数算法 常见的回答是:给对象中添加一个引用计数器,有地方引用&#xff0…...

Docker Overlay 网络的核心工作(以跨节点容器通信为例)

Docker 的 overlay 网络是一种基于 VXLAN(Virtual Extensible LAN)的多主机网络模式,专为 Docker Swarm 集群设计,用于实现跨节点的容器通信。它通过虚拟二层网络,允许容器在不同主机上像在同一局域网内一样通信。Dock…...

用 R 语言打造交互式叙事地图:讲述黄河源区生态变化的故事

目录 🌟 项目背景:黄河源头的生态变迁 🧰 技术栈介绍 🗺️ 最终效果预览 💻 项目构建步骤 1️⃣ 数据准备 2️⃣ 构建 Leaflet 地图 3️⃣ 使用 scrollama 实现滚动触发事件 4️⃣ 使用 R Markdown / Quarto 打包发布 🎬 效果展示截图 📦 完整代码仓库 …...

Java Stream常见误区解析:五大错误与规避方法

Java Stream API以函数式编程风格提供了一种强大的数据处理方式,使代码更简洁和可读。然而,误用Stream可能导致性能低下、错误频发或代码难以维护。本文将探讨开发者在使用Java Stream时最常见的五种错误,并提供规避方法。 1. 在Stream处理中…...

【树莓派Pico FreeRTOS】-中断服务与二值信号量

中断服务与二值信号量 RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 RAM,并支持高达 16MB 的片外闪存。 广泛的灵活 I/O 选项包括 I2C、SPI 和独特的可编程 I/O (PIO)。 FreeRTOS 由 Real Time Engineers Ltd. 独家拥有、开发和维护。FreeRTO…...

构建灵活可扩展的接口抽象层:支持多种后端数据存取的最佳实践

构建灵活可扩展的接口抽象层:支持多种后端数据存取的最佳实践 在现代应用开发中,后端数据存取的需求可能非常多样化:本地数据库、云存储服务、REST API,甚至是文件系统。因此,设计一套支持多种后端数据存取的接口抽象层是提高系统灵活性和可维护性的关键。本文将详细探讨…...

Scade 语言词法介绍

Scade 6 是一种具备形式化语法与形式化语义的领域特定语言(注1)。自2008年发布(注5)起,在 Scade Suite 产品系列中语言定义方面到目前未产生重要的改变(注2)。在下面的内容中将介绍Scade 语言的词法(注3)。 注1&#x…...

如何配置环境变量HADOOP_HOMEM、AVEN_HOME?不配置会怎么样

以下是在不同操作系统中配置 HADOOP_HOME 和 JAVA_HOME 环境变量的方法,以及不配置可能产生的后果: 配置 HADOOP_HOME - Windows系统:下载并解压Hadoop安装包,然后右键“此电脑”,选择“属性”,点击“高级…...

YOLO学习笔记 | 基于YOLOv8的植物病害检测系统

以下是基于YOLOv8的植物病害检测系统完整技术文档,包含原理分析、数学公式推导及代码实现框架。 基于YOLOv8的智能植物病害检测系统研究 摘要 针对传统植物病害检测方法存在的效率低、泛化性差等问题,本研究提出一种基于改进YOLOv8算法的智能检测系统。通过设计轻量化特征提…...

在已有的vue项目中使用vuex

介绍 Vuex 是一个用于 Vue.js 应用程序的状态管理模式 库。它充当应用程序中所有组件的集中存储,其规则确保状态只能以可预测的方式进行更改。 专门在vue中实现集中式状态(数据)管理的一个插件对vue应用中多个组件的共享状态进行集中式的管…...

基于uniapp的鸿蒙APP大数据量性能优化

文章目录 一、问题诊断与性能瓶颈分析1.1 大数据场景下的典型性能问题1.2 性能监测工具使用1.2.1 HBuilderX内置分析器1.2.2 鸿蒙DevEco工具链1.2.3 自制性能埋点 二、数据加载优化方案2.1 分页加载实现(带错误重试机制)2.2 数据流优化策略2.2.1 数据压缩…...

C++ 面向对象关键语法详解:override、虚函数、转发调用和数组引用传参-策略模式

int A(参数...) override { return 某个对象.A(参数...);} 一.目标 本文将用一个简单的“数学运算器”例子,从零解释以下 C 语法特性: virtual 虚函数 override 重写关键字 函数体内部的“转发调用” 数组引用作为函数参数 适合初学者和希望加深…...

山东科技大学深度学习考试回忆

目录 一、填空(五个空,十分) 二、选择题(五个,十分) 三、判断题(五个,五分) 四、论述题(四个,四十分) 五、计算题(二个&#xff…...

sql server 学习计划

目标定位(适用于开发人员、架构师、DBA) 精通 SQL Server 的数据建模、T-SQL 编程、并发控制、性能优化、索引策略 掌握事务、锁机制、统计信息、执行计划 能独立完成复杂系统的数据库设计、调优与可用性设计 具备解决大数据量、高并发、长事务、数据…...

宇树机器狗go2—slam建图(1)点云格式

0.前言 上一篇番外文章教大家如何在宇树机器狗go2的gazebo仿真环境中实现简单的导航运动,本期文章会教大家如何让宇树的机器狗go2在仿真环境中进行slam建图时经常会遇到的一些点云格式,在后续的slam建图和slam算法解析的时候会经常与这些点云信息打交道…...