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

news2025/4/21 5:12:34


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] = True
                col[j][d] = True
                k = (i // 3) * 3 + (j // 3)
                box[k][d] = True  # 第k 个箱子的d 是否存在
            # 保存空格的位置到spaces
            else:
                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长度时候说明已经填写完 ,返回true
            print("结果", board)
            return True
        i, j = spaces[pos]
        k = (i // 3) * 3 + (j // 3)
        for d in range(1, 10):  # 对这个位置尝试填充1-9
            if not row[i][d] and not col[j][d] and not box[k][d]:  # 满足为false 时候填入
                row[i][d] = True
                col[j][d] = True
                box[k][d] = True
                board[i][j] = str(d)
                if backtrack(pos + 1):
                    return True
                # 回溯
                row[i][d] = False
                col[j][d] = False
                box[k][d] = False
                board[i][j] = '.'  # 恢复空格
        return False

    backtrack(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]=True
                    col[j][d]=True
                    k=(i//3)*3+(j//3)
                    box[k][d]=True
                else:
                    spaces.append((i,j)) # 记录空格的坐标
        def  backtrack(pos):
            if pos ==len(spaces):#遍历完了所有空格
                return True
            i,j=spaces[pos] # 取出当前位置的空格坐标
            k=(i//3)*3+(j//3)
            for d in range(1,10):  # 尝试对该位置填充1-9
                
                if row[i][d]==False and col[j][d]==False and box[k][d]==False:
                    row[i][d]=True
                    col[j][d]=True
                    box[k][d]=True
                    board[i][j]=str(d)
                    if backtrack(pos+1):
                        return True
                    #不满足  回溯
                    row[i][d]=False
                    col[j][d]=False
                    box[k][d]=False
                    board[i][j]='.' 
            return False
        backtrack(0)

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

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

相关文章

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

近日,“鑫智奖 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图像最大的问题之一是什么?最终结果通常分辨率非常低。 这会导致很多不同的问题,特别是对于那些想要在内容或项目中使用这些…

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

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

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

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

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

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

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

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

在已有的vue项目中使用vuex

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

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

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

致远OA——自定义开发rest接口

文章目录 :apple: 业务流程 🍎 业务流程 代码案例: https://pan.quark.cn/s/57fa808c823f 官方文档: https://open.seeyoncloud.com/seeyonapi/781/https://open.seeyoncloud.com/v5devCTP/39/783.html 登录系统 —— 后台管理 —— 切换系…

No package docker-ce available问题的解决

安装docker时提示 rootk8s-node3 ~]# yum install -y docker-ce docker-ce-cli containerd.io Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.aliyun.com * extras: mirrors.aliyun.com * updates: mirrors.aliyun.com No packag…

群晖威联通飞牛等nas如何把宿主机硬盘挂接到可道云docker容器中

可道云系统是用户常用的一款面向个人用户的轻量级私有云存储工具,以高效管理和安全存储为核心,打造便捷的数字化办公体验。但是用户希望把原有其他磁盘中文件挂接到这个新系统中有很大的难度,主要是对linux文件系统理解有很大的误区,认为目录结构是固定的…

Uniapp:列表选择提示框

目录 一、出现场景二、效果展示三、具体使用 一、出现场景 在项目的开发过程中,有这样一种场景,就是点击按钮走后续的逻辑之前还需要选择前提条件,就一个条件的情况下如果使用弹出框就显示比较多余,列表选择提示框刚好能够满足我…

【python】django sqlite版本过低怎么办

方法一:下载最新版本 复制上面的内容的链接 在服务器上进行操作 wget https://sqlite.org/2025/sqlite-autoconf-3490100.tar.gz tar -zxvf sqlite-autoconf-3490100.tar.gz cd sqlite-autoconf-3490100 ./configure --prefix/usr/local make && make in…

山东大学软件学院创新项目实训开发日志(18)之对话自动生成标题设为用户第一次对话发的文字

本次功能的实现主要集中在后端,前端代码不用改变: 前端界面效果展示:

【机器学习】PCA-奇异值分解-上采样与下采样-傅里叶变换

1. PCA 主成分分析 主成分分析(PCA)是一种常用的数据降维方法。 它通过找到数据中方差最大的方向(主成分),将原始高维数据映射到较低维空间,同时尽可能保留原始信息。 数学实现上,通常通过协方…

【day8】调用AI接口,生成自动化测试用例

1、项目结构建议 project/ ├── api_docs/ # 存放接口文档 │ └── XX系统.swagger.json ├── ai_generator/ # AI测试用例生成模块 │ └── test_case_generator.py ├── tests/ # 生成的测试用例 │ └── test_user_api.py ├── conftest.py # pytest配置 ├─…