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

【递归与回溯深度解析:经典题解精讲(下篇)】—— Leetcode

文章目录

  • 有效的数独
  • 解数独
  • 单词搜索
  • 黄金矿工
  • 不同的路径|||

有效的数独

在这里插入图片描述
递归解法思路

  • 将每个数独的格子视为一个任务,依次检查每个格子是否合法。
    如果当前格子中的数字违反了数独规则(在行、列或 3×3 小方块中重复),直接返回 False。
    递归检查下一个格子,直到所有格子都检查完毕。
    如果所有格子都合法,则返回 True。
class Solution 
{// 使用三个布尔数组分别记录数独中行、列和3x3小方块中是否已经存在某个数字。bool row[9][10];    // row[i][num] 表示第 i 行是否已经存在数字 numbool col[9][10];    // col[j][num] 表示第 j 列是否已经存在数字 numbool grid[3][3][10]; // grid[i][j][num] 表示第 (i, j) 个 3x3 小方块中是否已经存在数字 num
public:bool isValidSudoku(vector<vector<char>>& board) {// 遍历整个 9x9 的棋盘for(int i = 0; i < 9; i++) // 遍历每一行{for(int j = 0; j < 9; j++) // 遍历每一列{// 如果当前格子不为空(即不是 '.')if(board[i][j] != '.'){int num = board[i][j] - '0'; // 将字符数字转换为整数// 检查当前数字 num 是否已经在当前行、列或 3x3 小方块中存在if(row[i][num] || col[j][num] || grid[i / 3][j / 3][num])return false; // 如果存在,说明数独无效,返回 false// 如果没有冲突,则将 num 标记为已存在row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = true;}}}// 如果遍历结束没有发现冲突,说明数独有效,返回 truereturn true;}
};

解数独

在这里插入图片描述
思路:回溯算法

  • 使用回溯法填充数独的空格。
    对于每个空格,尝试填入数字 1-9,并检查当前数字是否满足数独规则:
    当前数字在行中是否唯一。
    当前数字在列中是否唯一。
    当前数字在 3×3 小方块中是否唯一。
    如果满足规则,则递归求解下一个空格;如果不满足,则回溯到上一步继续尝试。
    当所有空格都填满且数独有效时,返回结果。
class Solution 
{// 使用三个布尔数组记录数独中行、列和3x3小方块中是否已经存在某个数字bool col[9][10];    // col[j][num] 表示第 j 列是否已经存在数字 numbool row[9][10];    // row[i][num] 表示第 i 行是否已经存在数字 numbool grid[3][3][10]; // grid[i][j][num] 表示第 (i, j) 个 3x3 小方块中是否已经存在数字 numpublic:// 主函数:解数独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] == '.') // 找到空格子{// 尝试填入数字 1 到 9for(int num = 1; num <= 9; num++){// 如果当前数字 num 在对应的行、列和小方块中都未出现if(!row[i][num] && !col[j][num] && !grid[i / 3][j / 3][num]){// 填入数字board[i][j] = '0' + num; // 将整数转换为字符// 标记当前数字在行、列和小方块中已存在row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = true;// 递归求解下一步if(dfs(board) == true) return true;// 如果递归返回 false,说明当前解不正确,需要回溯board[i][j] = '.'; // 恢复空格子row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = false; // 取消标记}}// 如果 1-9 都无法填入,返回 falsereturn false;}}}// 如果遍历完所有格子都有效,返回 truereturn true;}
};

单词搜索

在这里插入图片描述
思路:回溯+深度优先搜索 (DFS)

  • 问题是查找网格中是否存在给定单词。
    遍历网格中的每个字符作为起点,使用回溯和 DFS 搜索路径:
    如果当前字符匹配单词的第一个字符,则继续递归搜索四个方向(上下左右)。
    使用标志位(例如临时修改字符)避免重复访问。
    如果路径不符合要求,则回溯到上一层。
    如果成功找到完整路径,则返回 true;否则继续尝试其他起点。
class Solution 
{bool vis[7][7]; // 标记每个网格点是否已被访问,避免重复使用int m, n;       // 网格的行数 (m) 和列数 (n)public:// 主函数,判断单词是否存在bool exist(vector<vector<char>>& board, string word) {// 初始化网格大小m = board.size(); n = board[0].size();// 遍历网格中的每一个字符,寻找与单词第一个字符匹配的位置作为起点for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){// 如果当前字符是单词的第一个字符if(board[i][j] == word[0]){vis[i][j] = true; // 标记当前格子为已访问// 从当前格子开始深度优先搜索if(dfs(board, i, j, word, 1)) return true;vis[i][j] = false; // 回溯时取消标记}}}return false; // 如果所有起点都不能找到完整单词,则返回 false}// 方向数组,用于表示上下左右的移动int dx[4] = {0, 0, -1, 1}; // 水平方向int dy[4] = {-1, 1, 0, 0}; // 垂直方向// 深度优先搜索函数bool dfs(vector<vector<char>>& board, int i, int j, string& word, int pos){// 递归终止条件:如果已经匹配到单词的最后一个字符,返回 trueif(pos == word.size())return true;// 遍历当前格子的四个方向for(int k = 0; k < 4; k++){int x = i + dx[k]; // 新的行坐标int y = j + dy[k]; // 新的列坐标// 判断新位置是否合法且匹配当前单词字符if(x >= 0 && y >= 0 && x < m && y < n && !vis[x][y] && board[x][y] == word[pos]){vis[x][y] = true; // 标记新位置为已访问// 递归继续搜索下一个字符if(dfs(board, x, y, word, pos + 1)) return true;vis[x][y] = false; // 回溯时取消标记}}return false; // 如果四个方向都找不到匹配路径,返回 false}
};

黄金矿工

在这里插入图片描述
思路:回溯+深度优先搜索 (DFS)

  • 在网格中寻找一条路径,使得采集的黄金总量最大,路径可以在上下左右四个方向移动,但不能重复访问。
    遍历网格中的每个点作为起点,使用回溯和 DFS 搜索:
    当前点的黄金加入总和。
    标记当前点已访问,递归搜索四个方向。
    搜索完成后,恢复当前点状态(回溯)。
    返回所有路径中黄金总和的最大值。
class Solution 
{bool vis[16][16]; // 标记网格中的格子是否已被访问int m, n;         // 网格的行数 (m) 和列数 (n)int dx[4] = {0, 0, -1, 1}; // 表示移动的水平方向:左右int dy[4] = {-1, 1, 0, 0}; // 表示移动的垂直方向:上下int ret; // 记录黄金路径的最大总量public:// 主函数,返回可以采集的最大黄金总量int getMaximumGold(vector<vector<int>>& grid) {m = grid.size();  // 获取网格的行数n = grid[0].size(); // 获取网格的列数// 遍历网格中的每一个格子for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(grid[i][j]) // 如果当前格子有黄金{vis[i][j] = true; // 标记当前格子为已访问dfs(grid, i, j, grid[i][j]); // 从当前格子开始深度优先搜索vis[i][j] = false; // 回溯时恢复状态}}}return ret; // 返回找到的最大黄金总量}// 深度优先搜索函数void dfs(vector<vector<int>>& grid, int i, int j, int path){ret = max(ret, path); // 更新最大黄金总量// 遍历四个方向for(int k = 0; k < 4; k++){int x = i + dx[k]; // 计算新的行坐标int y = j + dy[k]; // 计算新的列坐标// 判断新坐标是否合法、是否未访问以及是否有黄金if(x >= 0 && y >= 0 && x < m && y < n && !vis[x][y] && grid[x][y]){vis[x][y] = true; // 标记新位置为已访问dfs(grid, x, y, grid[x][y] + path); // 递归搜索vis[x][y] = false; // 回溯时恢复状态}}}
};

不同的路径|||

在这里插入图片描述
思路:回溯+深度优先搜索 (DFS)

  • 在网格中寻找一条路径,要求:
    从起点走到终点。
    必须经过所有空格,不能遗漏也不能重复。
    使用回溯法遍历网格:
    遍历网格找到起点,并统计需要经过的空格数量。
    从起点出发,递归搜索四个方向:
    标记当前点已访问。
    如果到达终点且已访问所有空格,路径计数+1。
    搜索完成后,恢复当前点状态(回溯)。
    返回所有满足条件的路径总数。
class Solution 
{int m, n, step; // m 和 n 是网格的行列大小,step 是需要经过的格子总数bool vis[21][21]; // 标记网格中的格子是否已被访问,避免重复访问int dx[4] = {0, 0, -1, 1}; // 表示水平方向的移动(左右)int dy[4] = {-1, 1, 0, 0}; // 表示垂直方向的移动(上下)int ret; // 记录所有满足条件的路径数public:// 主函数:返回所有满足条件的路径数int uniquePathsIII(vector<vector<int>>& grid) {m = grid.size();  // 获取网格的行数n = grid[0].size(); // 获取网格的列数int bx = 0, by = 0; // 起点坐标// 遍历网格,初始化起点和统计需要经过的格子总数for(int i = 0; i < m; i++){for(int j = 0; j < n; j++){if(grid[i][j] == 0) step++; // 统计值为 0 的空格else if(grid[i][j] == 1)   // 找到起点{bx = i;by = j;}}}step += 2; // 包括起点和终点在内,总共需要经过的格子数// 从起点开始进行 DFSvis[bx][by] = true; // 标记起点为已访问dfs(grid, bx, by, 1); // 起点已访问,计数为 1return ret; // 返回有效路径的数量}// 深度优先搜索函数void dfs(vector<vector<int>>& grid, int i, int j, int count){// 如果当前格子是终点(值为 2)if(grid[i][j] == 2){// 如果路径经过了所有需要访问的格子if(count == step)ret++; // 计数器加 1return;}// 遍历当前格子的四个方向for(int k = 0; k < 4; k++){int x = i + dx[k]; // 新的行坐标int y = j + dy[k]; // 新的列坐标// 判断新位置是否合法if(x >= 0 && y >= 0 && x < m && y < n && grid[x][y] != -1 && !vis[x][y]){vis[x][y] = true; // 标记新位置为已访问dfs(grid, x, y, count + 1); // 递归搜索下一步vis[x][y] = false; // 回溯时恢复状态}}}
};

相关文章:

【递归与回溯深度解析:经典题解精讲(下篇)】—— Leetcode

文章目录 有效的数独解数独单词搜索黄金矿工不同的路径||| 有效的数独 递归解法思路 将每个数独的格子视为一个任务&#xff0c;依次检查每个格子是否合法。 如果当前格子中的数字违反了数独规则&#xff08;在行、列或 33 小方块中重复&#xff09;&#xff0c;直接返回 Fals…...

Spring boot处理跨域问题

Spring boot处理跨域问题 方案一方案二推荐解决方案注意 方案一 实现WebMvcConfigurer的addCorsMappings方法 Configuration public class InterceptorConfig implements WebMvcConfigurer {Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMappin…...

每日小题打卡

目录 幂次方 手机键盘 简单排序 校庆 性感素数 幂次方 题目描述 对任意正整数 N&#xff0c;计算 X^Nmod233333 的值。 输入格式 共一行&#xff0c;两个整数 X 和 N。 输出格式 共一行&#xff0c;一个整数&#xff0c;表示 X^Nmod233333 的值。 数据范围 1≤…...

RockyLinux介绍及初始化

文章目录 一、背景二、下载 RockyLinux9 镜像三、环境初始化四、安装 Docker 环境 一、背景 这里讲一个小故事&#xff1a; 我们都知道Linux 内核是由芬兰计算机科学家林纳斯托瓦兹 (Linus Torvalds) 于 1991 年首次开发的&#xff0c;随后有一个非常重要的公司RetHat成立&am…...

2024年12月青少年软件编程(C语言/C++)等级考试试卷(三级)

2024.12青少年软件编程&#xff08;C语言三级&#xff09;等级考试试卷 1.最近的斐波那契数 题目描述 斐波那契数列 Fn的定义为&#xff1a;对n≥0有Fn2Fn1Fn、初始值为 F00和F11。所谓与给定的整数N最近的斐波那契数是指与N的差之绝对值最小的斐波那契数。 本题就请你为任意给…...

【Leecode】Leecode刷题之路第92天之反转链表II

题目出处 92-反转链表II-题目出处 题目描述 个人解法 思路&#xff1a; todo代码示例&#xff1a;&#xff08;Java&#xff09; todo复杂度分析 todo官方解法 92-反转链表II-官方解法 前言 链表的操作问题&#xff0c;一般而言面试&#xff08;机试&#xff09;的时候不…...

StableAnimator模型的部署:复旦微软提出可实现高质量和高保真的ID一致性人类视频生成

文章目录 一、项目介绍二、项目部署模型的权重下载提取目标图像的关节点图像&#xff08;这个可以先不看先用官方提供的数据集进行生成&#xff09;提取人脸&#xff08;这个也可以先不看&#xff09;进行图片的生成 三、模型部署报错 一、项目介绍 由复旦、微软、虎牙、CMU的…...

3.阿里云flinkselectdb-py作业

1.概述 Python API中文文档 本文介绍在阿里云实时计算flink中使用python作业&#xff0c;把oss中的数据同步数据到阿里云selectdb的过程。python简单的语法特性更适合flink作业的开发&#xff1b; 先说结论: 在实际开发中遇到了很多问题&#xff0c;导致python作业基本基本无法…...

MATLAB语言的网络编程

标题&#xff1a;MATLAB中的网络编程&#xff1a;深入探索与实践 一、引言 在现代科学和工程领域中&#xff0c;网络编程已经成为了数据处理、信号分析、模型构建等众多任务中不可或缺的一环。MATLAB作为一款强大的数学计算软件&#xff0c;不仅提供了丰富的数值计算功能&…...

深入浅出 Linux 操作系统

深入浅出 Linux 操作系统 引言 在当今数字化的时代&#xff0c;Linux 操作系统无处不在。从支撑互联网巨头庞大的数据中心&#xff0c;到嵌入智能家居设备的微型芯片&#xff0c;Linux 都发挥着关键作用。然而&#xff0c;对于许多人来说&#xff0c;Linux 仍笼罩着一层神秘的…...

golang实现生产者消费者模式

在Go语言中&#xff0c;生产者消费者模式可以通过使用Goroutines和Channels来实现。Goroutines允许并发执行&#xff0c;而Channels则用于在生产者和消费者之间安全地传递数据。 生产者消费者模式的基本思路 生产者&#xff1a;负责生成数据并将其放入一个共享的缓冲区&#xf…...

自动化测试-Pytest测试

目录 pytest简介 基本测试实例 编写测试文件 执行测试 pytest运行时参数 mark标记 Fixture pytest插件 Allure测试报告 测试步骤 pytest简介 Pytest‌是一个非常流行的Python测试框架&#xff0c;它支持简单的单元测试和复杂的功能测试&#xff0c;具有易于上手、功…...

Ingress-Nginx Annotations 指南:配置要点全方面解读(下)

文章目录 1.HTTP2 Push Preload2.Server Alias3.Server snippet4.Client Body Buffer Size5.External Authentication6.Global External Authentication7.Rate Limiting8.Global Rate Limiting9.Permanent Redirect10.Permanent Redirect Code11.Temporal Redirect12.SSL Passt…...

【QED】等式构造

文章目录 题目题目描述输入输出格式数据范围测试样例 思路代码复杂度分析时间复杂度空间复杂度 题目 题目链接&#x1f517; 题目描述 有关 「上述等式为何正确」 的问题解决了&#xff0c;然而 「如何构造出上述那种让人啼笑皆非的正确等式」 成为了一个新的问题。 我们认…...

Kafka数据迁移全解析:同集群和跨集群

文章目录 一、同集群迁移二、跨集群迁移 Kafka两种迁移场景&#xff0c;分别是同集群数据迁移、跨集群数据迁移。 一、同集群迁移 应用场景&#xff1a; broker 迁移 主要使用的场景是broker 上线,下线,或者扩容等.基于同一套zookeeper的操作。 实践&#xff1a; 将需要新添加…...

Debian安装配置RocketMQ

安装配置 本次安装在/tools/rocket目录下 下载 wget https://dist.apache.org/repos/dist/release/rocketmq/5.3.1/rocketmq-all-5.3.1-bin-release.zip 解压缩 unzip rocketmq-all-5.3.1-bin-release.zip 如果出现以下报错 -bash: unzip: command not found可安装unzip工具后执…...

vue之axios基本使用

文章目录 1. axios 网络请求库2. axiosvue 1. axios 网络请求库 <body> <input type"button" value"get请求" class"get"> <input type"button" value"post请求" class"post"> <!-- 官网提供…...

三只脚的电感是什么东西?

最近在做加湿器&#xff0c;把水雾化的陶瓷片需要有专门的驱动电路。 我参考了某宝卖家的驱动板以及网上的开源项目&#xff0c;发现了驱动电路的核心就是一个三脚电感。 在此之前我都没注意过这玩意&#xff0c;三脚电感不也还是电感嘛&#xff1f; 今天我们就来看看三脚电…...

【数据库学习笔记】SQL触发器(例题+代码)

数据库SQL 1、触发器概念 &#xff08;1&#xff09;触发器&#xff08;trigger&#xff09;是用户定义在关系表上的一类由事件驱动的存储过程&#xff0c;由服务器自动激活。 &#xff08;2&#xff09;触发器可进行更为复杂的检查和操作&#xff0c;具有更精细和更强大的数…...

Unittest02|TestSuite、TestRunner、HTMLTestRunner、处理excel表数据、邮件接收测试结果

目录 八、测试套件TestSuite和测试运行器TestRunner 1、基本概念 2、创建和使用测试套件 3、 自动发现测试用例、创建测试套件、运行测试 4、生成html的测试报告&#xff1a;HTMLTestRunner 1️⃣导入HTMLTestRunner模块 2️⃣运行测试用例并生成html文件 九、unittest…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

1688商品列表API与其他数据源的对接思路

将1688商品列表API与其他数据源对接时&#xff0c;需结合业务场景设计数据流转链路&#xff0c;重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点&#xff1a; 一、核心对接场景与目标 商品数据同步 场景&#xff1a;将1688商品信息…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...