【递归与回溯深度解析:经典题解精讲(下篇)】—— 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
文章目录 有效的数独解数独单词搜索黄金矿工不同的路径||| 有效的数独 递归解法思路 将每个数独的格子视为一个任务,依次检查每个格子是否合法。 如果当前格子中的数字违反了数独规则(在行、列或 33 小方块中重复),直接返回 Fals…...
Spring boot处理跨域问题
Spring boot处理跨域问题 方案一方案二推荐解决方案注意 方案一 实现WebMvcConfigurer的addCorsMappings方法 Configuration public class InterceptorConfig implements WebMvcConfigurer {Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMappin…...
每日小题打卡
目录 幂次方 手机键盘 简单排序 校庆 性感素数 幂次方 题目描述 对任意正整数 N,计算 X^Nmod233333 的值。 输入格式 共一行,两个整数 X 和 N。 输出格式 共一行,一个整数,表示 X^Nmod233333 的值。 数据范围 1≤…...
RockyLinux介绍及初始化
文章目录 一、背景二、下载 RockyLinux9 镜像三、环境初始化四、安装 Docker 环境 一、背景 这里讲一个小故事: 我们都知道Linux 内核是由芬兰计算机科学家林纳斯托瓦兹 (Linus Torvalds) 于 1991 年首次开发的,随后有一个非常重要的公司RetHat成立&am…...
2024年12月青少年软件编程(C语言/C++)等级考试试卷(三级)
2024.12青少年软件编程(C语言三级)等级考试试卷 1.最近的斐波那契数 题目描述 斐波那契数列 Fn的定义为:对n≥0有Fn2Fn1Fn、初始值为 F00和F11。所谓与给定的整数N最近的斐波那契数是指与N的差之绝对值最小的斐波那契数。 本题就请你为任意给…...
【Leecode】Leecode刷题之路第92天之反转链表II
题目出处 92-反转链表II-题目出处 题目描述 个人解法 思路: todo代码示例:(Java) todo复杂度分析 todo官方解法 92-反转链表II-官方解法 前言 链表的操作问题,一般而言面试(机试)的时候不…...
StableAnimator模型的部署:复旦微软提出可实现高质量和高保真的ID一致性人类视频生成
文章目录 一、项目介绍二、项目部署模型的权重下载提取目标图像的关节点图像(这个可以先不看先用官方提供的数据集进行生成)提取人脸(这个也可以先不看)进行图片的生成 三、模型部署报错 一、项目介绍 由复旦、微软、虎牙、CMU的…...
3.阿里云flinkselectdb-py作业
1.概述 Python API中文文档 本文介绍在阿里云实时计算flink中使用python作业,把oss中的数据同步数据到阿里云selectdb的过程。python简单的语法特性更适合flink作业的开发; 先说结论: 在实际开发中遇到了很多问题,导致python作业基本基本无法…...
MATLAB语言的网络编程
标题:MATLAB中的网络编程:深入探索与实践 一、引言 在现代科学和工程领域中,网络编程已经成为了数据处理、信号分析、模型构建等众多任务中不可或缺的一环。MATLAB作为一款强大的数学计算软件,不仅提供了丰富的数值计算功能&…...
深入浅出 Linux 操作系统
深入浅出 Linux 操作系统 引言 在当今数字化的时代,Linux 操作系统无处不在。从支撑互联网巨头庞大的数据中心,到嵌入智能家居设备的微型芯片,Linux 都发挥着关键作用。然而,对于许多人来说,Linux 仍笼罩着一层神秘的…...
golang实现生产者消费者模式
在Go语言中,生产者消费者模式可以通过使用Goroutines和Channels来实现。Goroutines允许并发执行,而Channels则用于在生产者和消费者之间安全地传递数据。 生产者消费者模式的基本思路 生产者:负责生成数据并将其放入一个共享的缓冲区…...
自动化测试-Pytest测试
目录 pytest简介 基本测试实例 编写测试文件 执行测试 pytest运行时参数 mark标记 Fixture pytest插件 Allure测试报告 测试步骤 pytest简介 Pytest是一个非常流行的Python测试框架,它支持简单的单元测试和复杂的功能测试,具有易于上手、功…...
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】等式构造
文章目录 题目题目描述输入输出格式数据范围测试样例 思路代码复杂度分析时间复杂度空间复杂度 题目 题目链接🔗 题目描述 有关 「上述等式为何正确」 的问题解决了,然而 「如何构造出上述那种让人啼笑皆非的正确等式」 成为了一个新的问题。 我们认…...
Kafka数据迁移全解析:同集群和跨集群
文章目录 一、同集群迁移二、跨集群迁移 Kafka两种迁移场景,分别是同集群数据迁移、跨集群数据迁移。 一、同集群迁移 应用场景: broker 迁移 主要使用的场景是broker 上线,下线,或者扩容等.基于同一套zookeeper的操作。 实践: 将需要新添加…...
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"> <!-- 官网提供…...
三只脚的电感是什么东西?
最近在做加湿器,把水雾化的陶瓷片需要有专门的驱动电路。 我参考了某宝卖家的驱动板以及网上的开源项目,发现了驱动电路的核心就是一个三脚电感。 在此之前我都没注意过这玩意,三脚电感不也还是电感嘛? 今天我们就来看看三脚电…...
【数据库学习笔记】SQL触发器(例题+代码)
数据库SQL 1、触发器概念 (1)触发器(trigger)是用户定义在关系表上的一类由事件驱动的存储过程,由服务器自动激活。 (2)触发器可进行更为复杂的检查和操作,具有更精细和更强大的数…...
Unittest02|TestSuite、TestRunner、HTMLTestRunner、处理excel表数据、邮件接收测试结果
目录 八、测试套件TestSuite和测试运行器TestRunner 1、基本概念 2、创建和使用测试套件 3、 自动发现测试用例、创建测试套件、运行测试 4、生成html的测试报告:HTMLTestRunner 1️⃣导入HTMLTestRunner模块 2️⃣运行测试用例并生成html文件 九、unittest…...
2026年4月OpenClaw怎么集成?京东云小白6分钟部署及百炼APIKey配置步骤
2026年4月OpenClaw怎么集成?京东云小白6分钟部署及百炼APIKey配置步骤。OpenClaw(原Clawdbot)作为2026年主流的AI自动化助理平台,可通过阿里云轻量服务器实现724小时稳定运行,并快速接入钉钉,让AI在企业群聊…...
Qwen3-14B镜像部署避坑指南:RTX 4090D驱动/CUDA/内存精准匹配
Qwen3-14B镜像部署避坑指南:RTX 4090D驱动/CUDA/内存精准匹配 1. 镜像概述与核心优势 Qwen3-14B私有部署镜像是一款专为RTX 4090D显卡优化的开箱即用解决方案。这个镜像最大的特点就是解决了大模型部署中最让人头疼的环境配置问题。 想象一下,你拿到一…...
万兴剧厂AI漫剧APP2025推荐,打造个性化漫剧体验
万兴剧厂AI漫剧APP2025推荐,打造个性化漫剧体验在当今数字化娱乐的浪潮中,漫剧以其独特的表现形式和丰富的内容吸引了众多用户。据《2025中国数字娱乐行业发展报告》显示,2025年漫剧市场规模持续增长,用户对于优质漫剧的需求也日益…...
立创庐山派K230 RT-Smart GPIO驱动开发实战:从零构建LED控制应用
1. 庐山派K230开发板与RT-Smart系统初探 庐山派K230开发板是当前嵌入式开发领域的热门硬件平台,搭载了双核处理器架构,能够同时运行Linux和RT-Smart实时操作系统。RT-Smart作为一款轻量级实时操作系统,特别适合需要精确时序控制的嵌入式应用场…...
Rocky Linux 9.4 Minimal安装后必做的10件事:安全加固、性能优化与开发环境搭建
Rocky Linux 9.4 Minimal安装后必做的10件事:安全加固、性能优化与开发环境搭建 当你完成Rocky Linux 9.4 Minimal的安装,面对那个极简的命令行界面时,可能会感到一丝茫然。这个"裸"系统虽然轻量,但距离生产环境或高效开…...
保姆级教程:用SolidWorks URDF插件把你的机械设计变成Gazebo仿真模型
从SolidWorks到Gazebo:机械设计仿真全流程实战指南 机械工程师们常常面临一个挑战:如何在虚拟环境中快速验证设计方案的可行性?SolidWorks作为主流的三维设计工具,与Gazebo这一强大的机器人仿真平台结合,能够实现从概念…...
Omni-Vision Sanctuary 网络协议分析辅助:可视化网络数据包与流量模式识别
Omni-Vision Sanctuary 网络协议分析辅助:可视化网络数据包与流量模式识别 1. 网络数据可视化的新思路 网络工程师每天面对海量的数据包和流量日志,传统的分析工具往往需要依赖复杂的命令行操作和专业图表解读。而Omni-Vision Sanctuary模型为我们提供…...
rust-bert 多语言翻译实战:支持 100+ 语言的智能翻译系统
rust-bert 多语言翻译实战:支持 100 语言的智能翻译系统 【免费下载链接】rust-bert Rust native ready-to-use NLP pipelines and transformer-based models (BERT, DistilBERT, GPT2,...) 项目地址: https://gitcode.com/gh_mirrors/ru/rust-bert rust-ber…...
ClaudeCode 入门详细教程,手把手带你Vibe Coding
本文使用 Mac 进行演示。主要是在安装环节有环境差异。 1. Claude Code 简介 Claude Code 是 Anthropic 推出的面向开发者的 AI 编程协作工具。Claude Code 的核心目标是理解你的整个项目,并参与到真实的编码、修改和重构过程中。Claude Code 不是一个代码生成器&…...
从下载到运行:Pi0模型完整部署指南,适合新手入门
从下载到运行:Pi0模型完整部署指南,适合新手入门 1. 项目简介:什么是Pi0? Pi0是一个视觉-语言-动作流模型,专门为通用机器人控制设计。简单来说,它能让机器人“看懂”周围环境,“听懂”你的指…...
