【递归与回溯深度解析:经典题解精讲(下篇)】—— 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; // 回溯时恢复状态}}}
};

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

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

相关文章

Llama 3 预训练(二)

目录 3. 预训练 3.1 预训练数据 3.1.1 网络数据筛选 PII 和安全过滤 文本提取与清理 去重&#xff08;De-duplication&#xff09; 启发式过滤&#xff08;Heuristic Filtering&#xff09; 基于模型的质量过滤 代码和数学推理数据处理 多语言数据处理 3.1.2 确定数…

Mono里运行C#脚本8—mono_image_storage_open打开EXE文件

Mono里运行C#脚本8—mono_image_storage_open打开EXE文件 前面分析哈希表的实现,以及文件打开的底层函数,还有保存到HASH表里的数据结构。 static MonoImageStorage * mono_image_storage_open (const char *fname) { char *key = NULL; key = mono_path_resolve_symlinks…

前端项目 node_modules依赖报错解决记录

1.首先尝试解决思路 npm报错就切换yarn &#xff0c; yarn报错就先切换npm删除 node_modules 跟 package-lock.json文件重新下载依 2. 报错信息&#xff1a; Module build failed: Error: Missing binding D:\vue-element-admin\node_modules\node-sass\vendor\win32-x64-8…

双指针——查找总价格为目标值的两个商品

一.题目描述 LCR 179. 查找总价格为目标值的两个商品 - 力扣&#xff08;LeetCode&#xff09; 二.题目解析 这个题目非常简单&#xff0c;其实就是判断有没有两个数加起来等于target。 三.算法解析 1.暴力解法 暴力解法的话我们可以枚举出所有的情况&#xff0c;然后判…

sqlserver镜像设置

本案例是双机热备&#xff0c;只设置主体服务器&#xff08;主&#xff09;和镜像服务器&#xff08;从&#xff09;&#xff0c;不设置见证服务器 设置镜像前先检查是否启用了 主从服务器数据库的 TCP/IP协议 和 RemoteDAC &#xff08;1&#xff09;打开SQL Server配置管理器…

Elasticsearch:analyzer(分析器)

一、概述 可用于将字符串字段转换为单独的术语&#xff1a; 添加到倒排索引中&#xff0c;以便文档可搜索。级查询&#xff08;如 生成搜索词的 match查询&#xff09;使用。 分析器分为内置分析器和自定义的分析器&#xff0c;它们都是由若干个字符过滤器&#xff08;chara…

ElementPlus 自定义封装 el-date-picker 的快捷功能

文章目录 需求分析 需求 分析 我们看到官网上给出的案例如下&#xff0c;但是不太满足我们用户想要的快捷功能&#xff0c;因为不太多&#xff0c;因此需要我们自己封装一些&#xff0c;方法如下 外部自定义该组件的快捷内容 export const getPickerOptions () > {cons…

低代码开发平台排名2024

低代码开发平台在过去几年中迅速崛起&#xff0c;成为企业数字化转型的重要工具。这些平台通过可视化界面和拖放组件&#xff0c;使业务人员和技术人员都能快速构建应用程序&#xff0c;大大缩短了开发周期。以下是一些在2024年值得关注和使用的低代码开发平台。 一、Zoho Cre…

Substrate Saturday 回顾:如何利用 Polkadot Cloud 扩展 Solana 网络服务?

Lollipop 是一个为 Solana 生态系统设计的创新解决方案&#xff0c;与传统的 Layer 2 解决方案不同&#xff0c;Lollipop 通过其独特的 Network Extensions 设计&#xff0c;避免了生态系统的碎片化&#xff0c;同时为开发者提供了定制化的运行环境。Lollipop 旨在解决传统 rol…

Java重要面试名词整理(十):Kafka

文章目录 Kafka简介相关概念Kraft集群 Kafka收发消息梳理客户端工作机制消费者分组消费机制生产者拦截器机制消息序列化机制消息分区路由机制生产者消息缓存机制发送应答机制生产者消息幂等性生产者消息事务 Kafka集群架构设计-Kafka的Zookeeper元数据梳理Leader Partition选举…

计算机网络——期末复习(4)协议或技术汇总、思维导图

思维导图 协议与技术 物理层通信协议&#xff1a;曼彻斯特编码链路层通信协议&#xff1a;CSMA/CD &#xff08;1&#xff09;停止-等待协议&#xff08;属于自动请求重传ARQ协议&#xff09;&#xff1a;确认、否认、重传、超时重传、 &#xff08;2&#xff09;回退N帧协…

【MySQL学习笔记】关于索引

文章目录 【MySQL学习笔记】关于索引1.索引数据结构2.索引存储3.联合索引3.1 联合索引的b树结构3.2 索引覆盖&#xff1f;回表&#xff1f;3.3 联合索引最左匹配原则3.5 索引下推 4.索引失效 【MySQL学习笔记】关于索引 1.索引数据结构 索引是一种能提高查询速度的数据结构。…

D104【python 接口自动化学习】- pytest进阶参数化用法

day104 pytest参数化parametrize单参数 学习日期&#xff1a;20241223 学习目标&#xff1a;pytest基础用法 -- pytest参数化parametrize单参数 学习笔记&#xff1a; 参数化 parametrize 参数化可以组装测试数据&#xff0c;在测试前定义好测试数据&#xff0c;并在测试用…

Node.JS 版本管理工具 Fnm 安装及配置(Windows)

安装流程可参考&#xff1a;fnm 安装及配置(Windows)_fnm安装-CSDN博客 然后就是在git bash如何生效 在 Git Bash 中使用 fnm 需要确保你正确设置了环境变量。你可以按照以下步骤进行配置&#xff1a; 1. **打开 Git Bash**&#xff1a; 启动 Git Bash。 2. **编辑 .bas…

第T4周:TensorFlow实现猴痘识别(Tensorboard的使用)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目标&#xff1a; 1、学习tensorboard的使用 具体实现&#xff1a; &#xff08;一&#xff09;环境&#xff1a; 语言环境&#xff1a;Python 3.10 编 译 器…

Docker-构建自己的Web-Linux系统-镜像webtop:ubuntu-kde

介绍 安装自己的linux-server,可以作为学习使用&#xff0c;web方式访问&#xff0c;基于ubuntu构建开源项目 https://github.com/linuxserver/docker-webtop安装 docker run -d -p 1336:3000 -e PASSWORD123456 --name webtop lscr.io/linuxserver/webtop:ubuntu-kde登录 …

vue3 ref reactive响应式数据,赋值的问题、解构失去响应式问题

在 Vue3 中&#xff0c;使用 ref 和 reactive 创建响应式数据时&#xff0c;赋值操作和解构赋值存在一些需要注意的事项。以下是对这些问题的详细解答以及代码示例&#xff1a; ref 和 reactive 的基本用法 ref&#xff1a;主要用于基本数据类型&#xff08;如 Number、String、…

小米路由器开启SSH,配置阿里云ddns,开启外网访问SSH和WEB管理界面

文章目录 前言一、开启SSH二、配置阿里云ddns1.准备工作2.创建ddns脚本3.添加定时任务 三、开启外网访问SSH和WEB管理界面1、解除WEB管理页面访问限制2.手动添加防火墙端口转发规则&#xff0c;开启外网访问WEB管理和SSH 前言 例如&#xff1a;随着人工智能的不断发展&#xf…

什么是ESC ---- 防止车辆打滑并提高驾驶时稳定性的技术

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 所谓鸡汤&#xff0c;要么蛊惑你认命&#xff0c;要么怂恿你拼命&#xff0c;但都是回避问题的根源&…

LinkedList类 (链表)

目录 一. LinkedList 基本介绍 二. LinkedList 中的法及其应用 1. 添加元素 (1) add() (2) addAll() (3) addFirst() (4) addLast() 2. 删除元素 (1) remove() (2) removeAll() (3) removeFirst() (4) removeLast() 3. 遍历元素 (1) for 循环遍历 (2) for - each …