专题三:穷举vs暴搜vs深搜vs回溯vs剪枝

> 作者:დ旧言~
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:了解什么是穷举vs暴搜vs深搜vs回溯vs剪枝,并且掌握其算法。

> 毒鸡汤:有些事情,总是不明白,所以我不会坚持。早安!

> 专栏选自:递归、搜索与回溯算法_დ旧言~的博客-CSDN博客

> 望小伙伴们点赞👍收藏✨加关注哟💕💕

一、算法讲解

什么是回溯算法:

  • 回溯算法是⼀种经典的递归算法,通常⽤于解决组合问题、排列问题和搜索问题等。
  • 回溯算法的基本思想:从⼀个初始状态开始,按照⼀定的规则向前搜索,当搜索到某个状态⽆法前进时,回退到前⼀个状态,再按照其他的规则搜索。回溯算法在搜索过程中维护⼀个状态树,通过遍历状态树来实现对所有可能解的搜索。
  • 回溯算法的核⼼思想:“试错”,即在搜索过程中不断地做出选择,如果选择正确,则继续向前搜索;否则,回退到上⼀个状态,重新做出选择。回溯算法通常⽤于解决具有多个解,且每个解都需要搜索才能找到的问题。

回溯算法的模板:

void backtrack(vector<int>& path, vector<int>& choice, ...) {// 满⾜结束条件if (/* 满⾜结束条件 */) {// 将路径添加到结果集中res.push_back(path);return;}// 遍历所有选择for (int i = 0; i < choices.size(); i++) {// 做出选择path.push_back(choices[i]);// 做出当前选择后继续搜索backtrack(path, choices);// 撤销选择path.pop_back();}
}

其中, path 表⽰当前已经做出的选择, choices 表⽰当前可以做的选择。在回溯算法中,我们需
要做出选择,然后递归地调⽤回溯函数。如果满⾜结束条件,则将当前路径添加到结果集中;否则,我们需要撤销选择,回到上⼀个状态,然后继续搜索其他的选择。

回溯算法的时间复杂度通常较⾼,因为它需要遍历所有可能的解。但是,回溯算法的空间复杂度较低,因为它只需要维护⼀个状态树。在实际应⽤中,回溯算法通常需要通过剪枝等⽅法进⾏优化,以减少搜索的次数,从⽽提⾼算法的效率。

总结:

回溯算法是⼀种⾮常重要的算法,可以解决许多组合问题、排列问题和搜索问题等。回溯算法的核⼼思想是搜索状态树,通过遍历状态树来实现对所有可能解的搜索。回溯算法的模板⾮常简单,但是实现起来需要注意⼀些细节,⽐如如何做出选择、如何撤销选择等。

二、算法习题


2.1 第一题

题目链接:46. 全排列 - 力扣(LeetCode)

题目描述:

算法思路:

典型的回溯题⽬,我们需要在每⼀个位置上考虑所有的可能情况并且不能出现重复。通过深度优先搜索的⽅式,不断地枚举每个数在当前位置的可能性,并回溯到上⼀个状态,直到枚举完所有可能性,得到正确的结果。

每个数是否可以放⼊当前位置,只需要判断这个数在之前是否出现即可。具体地,在这道题⽬中,我们可以通过⼀个递归函数 backtrack 和标记数组 visited 来实现全排列。

递归函数设计:

void backtrack(vector<vector<int>>& res, vector<int>& nums, vector<bool>& visited, vector<int>& ans, int step, int len)

  • 参数:step(当前需要填⼊的位置),len(数组⻓度);
  • 返回值:⽆;
  • 函数作⽤:查找所有合理的排列并存储在答案列表中。

递归流程如下:

1. ⾸先定义⼀个⼆维数组 res ⽤来存放所有可能的排列,⼀个⼀维数组 ans ⽤来存放每个状态的排列,⼀个⼀维数组 visited 标记元素,然后从第⼀个位置开始进⾏递归;

2. 在每个递归的状态中,我们维护⼀个步数 step,表⽰当前已经处理了⼏个数字;

3. 递归结束条件:当 step 等于 nums 数组的⻓度时,说明我们已经处理完了所有数字,将当前数组存⼊结果中;

4. 在每个递归状态中,枚举所有下标 i,若这个下标未被标记,则使⽤ nums 数组中当前下标的元
素:

  • 将 visited[i] 标记为 1;
  • ans 数组中第 step 个元素被 nums[i] 覆盖;
  • 对第 step+1 个位置进⾏递归;
  • 将 visited[i] 重新赋值为 0,表⽰回溯;

5. 最后,返回 res。

  • 特别地,我们可以不使⽤标记数组,直接遍历 step 之后的元素(未被使⽤),然后将其与需要递归的位置进⾏交换即可。

代码呈现:

class Solution {vector<vector<int>> ret;vector<int> path;bool check[7];public:vector<vector<int>> permute(vector<int>& nums) {dfs(nums);return ret;}void dfs(vector<int>& nums) {if (path.size() == nums.size()) {ret.push_back(path);return;}for (int i = 0; i < nums.size(); i++) {if (!check[i]) {path.push_back(nums[i]);check[i] = true;dfs(nums);// 回溯 -> 恢复现场path.pop_back();check[i] = false;}}}
};

2.2 第二题

题目链接:78. 子集 - 力扣(LeetCode)

题目描述:

算法思路:

为了获得 nums 数组的所有⼦集,我们需要对数组中的每个元素进⾏选择或不选择的操作,即 nums数组⼀定存在 2^(数组⻓度) 个⼦集。对于查找⼦集,具体可以定义⼀个数组,来记录当前的状态,并对其进⾏递归。

对于每个元素有两种选择:1. 不进⾏任何操作;2. 将其添加⾄当前状态的集合。在递归时我们需要保证递归结束时当前的状态与进⾏递归操作前的状态不变,⽽当我们在选择进⾏步骤 2 进⾏递归时,当前状态会发⽣变化,因此我们需要在递归结束时撤回添加操作,即进⾏回溯。

递归函数设计:

void dfs(vector<vector<int>>& res, vector<int>& ans, vector<int>& nums, int step)

  • 参数:step(当前需要处理的元素下标);
  • 返回值:⽆;
  • 函数作⽤:查找集合的所有⼦集并存储在答案列表中。

递归流程如下:

1. 递归结束条件:如果当前需要处理的元素下标越界,则记录当前状态并直接返回;
2. 在递归过程中,对于每个元素,我们有两种选择:

  • 不选择当前元素,直接递归到下⼀个元素;
  • 选择当前元素,将其添加到数组末尾后递归到下⼀个元素,然后在递归结束时撤回添加操作;

3. 所有符合条件的状态都被记录下来,返回即可。

代码呈现:

class Solution {vector<vector<int>> ret;vector<int> path;public:vector<vector<int>> subsets(vector<int>& nums) {dfs(nums, 0);return ret;}void dfs(vector<int>& nums, int pos) {if (pos == nums.size()) {ret.push_back(path);return;}// 选path.push_back(nums[pos]);dfs(nums, pos + 1);path.pop_back(); // 恢复现场// 不选dfs(nums, pos + 1);}
};

三、结束语 

今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。

​​ 

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

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

相关文章

停更期李子柒品牌线上破亿,电商内容营销策略怎样重塑升级?

11月13日&#xff0c;李子柒在接受新华网记者的专访时被问到了“未来的商业化考虑”。她表示&#xff1a;“肯定会有这方面的考虑&#xff0c;只是目前还没有特别明确的规划。我就想继续做我自己喜欢的事情&#xff0c;如果这件事情能够被认同&#xff0c;而且它是有价值的&…

2020年国赛高教杯数学建模E题校园供水系统智能管理解题全过程文档及程序

2020年国赛高教杯数学建模 E题 校园供水系统智能管理 原题再现 校园供水系统是校园公用设施的重要组成部分&#xff0c;学校为了保障校园供水系统的正常运行需要投入大量的人力、物力和财力。随着科学技术的发展&#xff0c;校园内已经普遍使用了智能水表&#xff0c;从而可以…

【SpringBoot】使用IDEA创建SpringBoot项目

1、使用SpringBoot脚手架创建 我们使用SpringBoot的脚手架Spring Initializr创建&#xff0c;如图所示&#xff1a; 2、选择SpringBoot版本 最开始做项目时候&#xff0c;组长说创建一个 springboot 2.5.4 的项目&#xff0c;mysql使用 5.6.X &#xff0c;maven使用是3.6.X…

MFC实现全屏功能

之前全屏都是参考&#xff1a; MFC单文档&#xff08;SDI&#xff09;全屏程序的实现 主要思路就是将各种菜单工具栏隐藏恢复。 随着MFC的升级&#xff0c;MFC框架本身就具备了全屏的功能。 微软有一个全屏实现类&#xff1a; CFullScreenImpl Class managing full-screen mod…

灰狼算法与蚁群算法的结合:一种新颖的优化方法

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

Mybatis要点总结

MyBatis 是一款优秀的 持久层 框架 &#xff0c;用于简化 JDBC 的开发。 Java Data Base Connectivity&#xff08;Java语言连接数据库&#xff09; 数据库连接池 数据库连接池的好处&#xff1a; 资源重用 提升系统响应速度 避免数据库连接遗漏 常见的数据库连接池&…

前缀和(八)矩阵区域和

1314. 矩阵区域和 给你一个 m x n 的矩阵 mat 和一个整数 k &#xff0c;请你返回一个矩阵 answer &#xff0c;其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和&#xff1a; i - k < r < i k, j - k < c < j k 且(r, c) 在矩阵内。 示例 1&…

不一样的CSS(4)--icon图标系列之svg

序言 上一节内容我们讲解了如何利用css去画一个五角星&#xff0c;其中包括了使用svg的方法&#xff0c;有些小伙伴们对svg的使用不是很了解&#xff0c;那么本节内容我们主要来讲一下&#xff0c;关于svg标签的的使用。 目录 序言一、svg的介绍二、安装SVG扩展插件三、SVG基…

读取文件进度条

一、widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QMenuBar> #include <QFileDialog> #include <QFile> #include <QDebug> #include <QTimer> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NA…

js this

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>this</title> </head> <body> <script>let fengfeng "枫枫"console.log(this)// alert("123")funct…

wordpress网站安装了Linux宝塔面板,限制IP地址访问网站,只能使用域名访问网站

一、Linux服务器安装Linux宝塔面板 这个步骤参考网上其他教程。 二、Linux宝塔面板部署wordpress网站 这个步骤参考网上其他教程&#xff0c;保证网站能够正常访问&#xff0c;并且使用Linux宝塔面板申请并部署了SSL证书&#xff0c;使用https协议默认443端口正常访问。 三…

软考高级架构-9.4.4-双机热备技术 与 服务器集群技术

一、双机热备 1、特点&#xff1a; 软硬件结合&#xff1a;系统由两台服务器&#xff08;主机和备机&#xff09;、一个共享存储&#xff08;通常为磁盘阵列柜&#xff09;、以及双机热备软件&#xff08;提供心跳检测、故障转移和资源管理功能的核心软件&#xff09;组成。 …

电子商务人工智能指南 1/6 - 搜索、广告和发现

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

论文 | EfficientRAG: Efficient Retriever for Multi-Hop Question Answering

1. 论文介绍与研究动机 本文提出了一个新的检索增强生成&#xff08;RAG&#xff09;方法——EfficientRAG&#xff0c;它专门用于解决复杂的多跳问题。在多跳问答中&#xff0c;问题的答案需要从多个信息源中检索并结合起来&#xff0c;远比单跳问题复杂&#xff0c;因此也更加…

超详细搭建PhpStorm+PhpStudy开发环境

刚开始接触PHP开发&#xff0c;搭建开发环境是第一步&#xff0c;网上下载PhpStorm和PhpStudy软件&#xff0c;怎样安装和激活就不详细说了&#xff0c;我们重点来看一看怎样搭配这两个开发环境。 前提&#xff1a;现在假设你已经安装完PhpStorm和PhpStudy软件。 我的PhpStor…

Linux U-Boot 启动流程详解

目录 一、引言 二、U-Boot 启动前的准备 三、U-Boot 的启动流程 1.第一阶段&#xff1a;SPL&#xff08;Secondary Program Loader&#xff09;启动 2.第二阶段&#xff1a;U-Boot 主程序初始化 3.第三阶段&#xff1a;内核加载 4.第四阶段&#xff1a;参数传递 5.第五阶…

[Redis#16] 事务 | vs Mysql | 命令 | WATCH的实现

目录 什么是事务 实现事务的方式 Redis 事务与 MySQL 事务的对比 应用场景&#xff1a;防止超卖 Lua 脚本增强 事务操作 MULTI & EXEC DISCARD WATCH WATCH 的实现原理 什么是事务 [MySQL#12] 事务(1) | ACID | commit | 回滚 | 常见操作 Redis 的事务和 MySQL…

day03-分析产品原型-课程

1. 开发流程 2. 分析产品原型 2.1 业务流程 产品原型图&#xff1a; 两个业务模块之间使用异步通信 2.2 查询课程列表-接口 https://apifox.com/apidoc/shared-3076deb7-ecde-4519-8e57-390d336aef4c 2.2.1 课表VO 前端课表的相关参数&#xff1a; 现在还不能一步到位&a…

电子商务人工智能指南 2/6 - 需求预测和库存管理

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

CANoe IG实现信号遍历

CANoe IG也可以实现信号遍历的功能&#xff0c;设置如下&#xff1a; 注意事项&#xff1a; 选择 Range of values&#xff0c;是实现信号设定值范围内&#xff08;6&#xff09;的遍历 Hold time 要设置成和周期一致&#xff0c;如果不一致&#xff0c;则信号变化和周期不一…