【回溯+剪枝】回溯算法的概念 全排列问题
文章目录
- 46. 全排列
- Ⅰ. 什么是回溯算法❓❓❓
- Ⅱ. 回溯算法的应用
- 1、组合问题
- 2、排列问题
- 3、子集问题
- Ⅲ. 解题思路:回溯 + 剪枝

46. 全排列
46. 全排列
给定一个不含重复数字的数组 nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。
示例 1:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入:nums = [0,1]
输出:[[0,1],[1,0]]
示例 3:
输入:nums = [1]
输出:[[1]]
提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums
中的所有整数 互不相同
Ⅰ. 什么是回溯算法❓❓❓
回溯算法是一种经典的递归算法,通常用于解决组合问题、排列问题和搜索问题等。
回溯算法的基本思想:从一个初始状态开始,按照一定的规则向前搜索,当搜索到某个状态无法前进时,回退到前一个状态,再按照其他的规则搜索。回溯算法在搜索过程中维护一个状态树,通过遍历决策树来实现对所有可能解的搜索。
回溯算法的核心思想:“试错”,即在搜索过程中不断地做出选择,如果选择正确,则继续向前搜索;否则,回退到上一个状态,重新做出选择。回溯算法通常用于解决具有多个解,且每个解都需要搜索才能找到的问题,也就是相当于是 枚举!
其实说白了,回溯就是深搜,只不过回溯更加强调返回操作对一些题的理解是很重要的,所以专门给这种理解起了个回溯的专用词!其实回溯是有模板的,但是给出模板之后反而会限制思维,会想着怎么根据模板出发,而不是从题目本身出发,这是不行的,所以这里并不提供什么模板去背诵,当我们真正理解了回溯之后,其实写出来代码就会发现是和模板类似的!
Ⅱ. 回溯算法的应用
1、组合问题
组合问题是指从给定的⼀组数(不重复)中选取出所有可能的 k
个数的组合。例如,给定数集 [1,2,3]
,要求选取 k=2
个数的所有组合。其结果为:
[1, 2]
[1, 3]
[2, 3]
2、排列问题
排列问题是指从给定的⼀组数(可重复)中选取出所有可能的 k
个数的排列。例如,给定数集 [1,2,3]
,要求选取 k=2
个数的所有排列。其结果为:
[1,2]
[2,1]
[1,3]
[3,1]
[2,3]
[3,2]
3、子集问题
子集问题是指从给定的一组数中选取出所有可能的子集,其中每个子集中的元素可以按照任意顺序排列。例如,给定数集 [1,2,3]
,要求选取所有可能的子集。其结果为:
Ⅲ. 解题思路:回溯 + 剪枝
首先根据题目要求,我们 需要两个全局变量 ret
和 path
,ret
就是我们最后要返回的结果集,而 path
是存放当前正在走的全排列的元素!为什么要将它们设置为全局变量,而不是在函数中作为引用传递,其实是简化了函数需要填充的内容,并且在一定程度上也简化了我们的操作,尤其是后面一些题目比较说 N
皇后的题目等等,如果用传引用的方式的话,其实是不太好控制的!虽说使用全局变量之后,在回溯的时候需要我们手动去恢复一下 path
的状态,但是这都是值得的!
对于这类排列组合的问题,我们最好是能画出一棵详细一点的决策树(不要想的高大上,其实就是把情况枚举出来的树而已),这样子有利于帮助我们理解其中要注意的细节,如下面的图片所示!
因为排列问题需要遍历所有的组合可能,包括顺序不同的组合可能,比如说 [1, 2]
和 [2, 1]
都需要满足,所以我们在排列问题中就不需要使用 index
来控制每次下一层也就是树枝之间的起始位置,只需要 每次都从数组下标为 0
开始遍历所有可能即可!
但是这里还有一个问题,就是可能会出现重复调用了某个 nums[i]
,比如说 [1, 2, 3]
中我们如果不对每个元素进行控制的话,可能会排列出 [1, 1, 1]
等情况,但是排列问题中我们 只能让每个元素都出现一次,所以需要使用一个 used
数组进行判断:
- 将
used
数组初始化为false
。 - 因为会出现重复的情况只在一条路径上,所以我们无需担心路径之间的重复,所以我们让
used[i]
为false
表示是nums[i]
还没走过,当我们在递归这条路径的下一个节点之前将used[i]
变成true
,此时下一个节点层就会知道该nums[i]
是走过的了,就不会再走了!然后回溯的时候将used[i]
变成false
,这样子对同一树层是没有影响的,只会对下一层的路径产生影响! - 简单地说,当我们 判断到
used[i] == true
,也就说明上一层已经将这个元素遍历过了,所以我们直接continue
即可!
说白了,上面的操作其实就是一个 剪枝 的操作!
对于递归函数出口,我们只需要判断一下 path
数组的长度,是不是等于题目给的 nums
的长度,是的话说明当前序列已经是完成的了,则添加到 ret
结果集中然后直接返回即可!
然后就是递归函数的主体,其实最重要的就是三步:
- 处理当前层节点(处理)
- 递归下一层节点(递归)
- 进行回溯后的处理,防止影响后面的结果(回溯)
可以结合下面的代码一起分析这个过程!
class Solution {
private:vector<vector<int>> ret; // 结果集vector<int> path; // 存放当前正在走的全排列的元素vector<bool> used; // 标记哪个元素已经走过了,用于剪枝操作,防止重复
public:vector<vector<int>> permute(vector<int>& nums) {used.resize(nums.size(), false);dfs(nums);return ret;}void dfs(vector<int>& nums){// 递归函数出口(将当前path添加到结果集中)if(path.size() == nums.size()){ret.push_back(path);return;}for(int i = 0; i < nums.size(); ++i) // 每次都是从0开始遍历,和组合问题不一样,排列问题需要遍历所有可能{// 进行剪枝操作,防止结果重复if(used[i] == true)continue;// 处理当前层节点path.push_back(nums[i]);used[i] = true;// 递归下一层节点dfs(nums);// 进行回溯后的处理,防止影响后面的结果path.pop_back();used[i] = false;}}
};
相关文章:

【回溯+剪枝】回溯算法的概念 全排列问题
文章目录 46. 全排列Ⅰ. 什么是回溯算法❓❓❓Ⅱ. 回溯算法的应用1、组合问题2、排列问题3、子集问题 Ⅲ. 解题思路:回溯 剪枝 46. 全排列 46. 全排列 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 …...

Flutter解决macbook M芯片Android Studio中不显示IOS真机的问题
下载了最新的Android Studio LadyBug 下载了最新的xcode16.2 结果,只有安卓真机才在Android studio显示, IOS真机只在xcode显示 IOS真机不在android studio显示。 解决方法是: 在终端运行如下命令: sudo xcode-select -s /Applic…...

自签证书的dockerfile中from命令无法拉取镜像而docker的pull命令能拉取镜像
问题现象: docker pull images拉取镜像正常 dockerfile中的from命令拉取镜像就会报出证书错误。报错信息如下: [bjxtbwj-kvm-test-jenkins-6-243 ceshi_dockerfile]$ docker build . [] Building 0.4s (3/3) FINISHED …...

【MySQL】--- 复合查询 内外连接
Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏: MySQL 🏠 基本查询回顾 假设有以下表结构: 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为…...

QT TLS initialization failed
qt使用QNetworkAccessManager下载文件(给出的链接可以在浏览器里面下载文件),下载失败, 提示“TLS initialization failed”通常是由于Qt在使用HTTPS进行文件下载时,未能正确初始化TLS(安全传输层协议&…...

系统学英语 — 句法 — 复合句
目录 文章目录 目录复合句型主语从句宾语从句表语从句定语从句状语从句同位语从句 复合句型 复合句型,即:从句。在英语中,除了谓语之外的所有句子成分都可以使用从句来充当。 主语从句 充当主语的句子,通常位于谓语之前&#x…...

指针的介绍2前
1.数组名的理解 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h>int main() {int arr[] { 1,2,3,4,5,6,7,8,9 };printf("&arr[0] %p\n", &arr[0]);printf("arr %p\n", arr);return 0; } 观察得到,数组名就是数组首…...

16.Word:石油化工设备技术❗【28】
目录 题目 NO1.2 NO3 NO4 题目 NO1.2 F12:另存为将“Word素材.docx”文件另存为“Word. docx”(“docx”为文件扩展名) 光标来到表格上方→插入→形状→新建画布→单击选中→格式→高度/宽度(格式→大小对话框→取消勾选✔锁定…...

Python-基础环境(01) 虚拟环境,Python 基础环境之虚拟环境,一篇文章助你完全搞懂!
Python的虚拟环境是一种工具,它能够创建一个隔离的独立Python环境。每个虚拟环境都有自己独立的Python解释器和安装的包,不会与其他虚拟环境或系统的全局Python环境发生冲突。虚拟环境特别适用于以下情况: 项目隔离:不同的项目可…...

Dest1ny漏洞库:用友 U8-CRM 系统 ajaxgetborrowdata.php 存在 SQL 注入漏洞
用友U8-CRM系统ajaxgetborrowdata.php存在SQL注入漏洞,文件多个方法存在SQL注入漏洞,未经身份验证的攻击者通过漏洞执行任意SQL语句,调用xp_cmdshell写入后门文件,执行任意代码,从而获取到服务器权限。 hunter app.n…...

java.sql.Date 弃用分析与替代方案
引言 java.sql.Date 是 Java 标准库中的一个类,它继承自 java.util.Date,主要用于在 Java 应用程序与数据库之间进行日期数据的传输。然而,随着 Java 语言的发展,java.sql.Date 以及其父类 java.util.Date 逐渐被认为存在设计缺陷…...

HarmonyOS:状态管理最佳实践
一、概述 在声明式UI编程范式中,UI是应用程序状态的函数,应用程序状态的修改会更新相应的UI界面。ArkUI采用了MVVM模式,其中ViewModel将数据与视图绑定在一起,更新数据的时候直接更新视图。如下图所示: ArkUI的MVVM模式…...

如何提高新产品研发效率
优化研发流程、采用先进工具、提升团队协作、持续学习与改进,是提高新产品研发效率的关键。其中,优化研发流程尤为重要。通过简化流程,减少不必要的环节和复杂性,企业可以显著提升研发效率。例如,采用自动化测试工具和…...

MongoDB平替数据库对比
背景 项目一直是与实时在线监测相关,特点数据量大,读写操作大,所以选用的是MongoDB。但按趋势来讲,需要有一款国产数据库可替代,实现信创要求。选型对比如下 1. IoTDB 这款是由清华大学主导的开源时序数据库&#x…...

JavaScript系列(46)-- WebGL图形编程详解
JavaScript WebGL图形编程详解 🎨 今天,让我们深入探讨JavaScript的WebGL图形编程。WebGL是一种基于OpenGL ES的JavaScript API,它允许我们在浏览器中渲染高性能的2D和3D图形。 WebGL基础概念 🌟 💡 小知识ÿ…...

YOLO目标检测4
一. 参考资料 《YOLO目标检测》 by 杨建华博士 本篇文章的主要内容来自于这本书,只是作为学习记录进行分享。 二. 环境搭建 (1) ubuntu20.04 anaconda安装方法 (2) 搭建yolo训练环境 # 首先,我们建议使用Anaconda来创建一个conda的虚拟环境 conda cre…...

十三先天记
没有一刻,只有当下在我心里。我像星星之间的空间一样空虚。他们是我看到的第一件事,我知道的第一件事。 在接下来的时间里,我意识到我是谁,我是谁。我知道星星在我上方,星球的固体金属体在我脚下。这个支持我的世界是泰…...

【论文阅读笔记】“万字”关于深度学习的图像和视频阴影检测、去除和生成的综述笔记 | 2024.9.3
论文“Unveiling Deep Shadows: A Survey on Image and Video Shadow Detection, Removal, and Generation in the Era of Deep Learning”内容包含第1节简介、第2-5节分别对阴影检测、实例阴影检测、阴影去除和阴影生成进行了全面的综述。第6节深入讨论了阴影分析࿰…...

Android AOP:aspectjx
加入引用 在整个项目的 build.gradle 中,添加 classpath "com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10" 可以看到测试demo的 gradle 版本是很低的。 基于 github 上的文档,可以看到原版只支持到 gradle 4.4 。后续需要使…...

前端【11】HTML+CSS+jQUery实战项目--实现一个简单的todolist
前端【8】HTMLCSSjavascript实战项目----实现一个简单的待办事项列表 (To-Do List)-CSDN博客 学过jQUery可以极大简化js代码的编写,基于之前实现的todolist小demo,了解如何使用 jQuery 来实现常见的动态交互功能。 修改后的js代码 关键点解析 动态添加…...

2025课题推荐——USBL与DVL数据融合的实时定位系统
准确的定位技术是现代海洋探测、海洋工程和水下机器人操作的基础。超短基线(USBL)和多普勒速度计(DVL)是常用的水下定位技术,但单一技术难以应对复杂环境。因此,USBL与DVL的数据融合以构建实时定位系统&…...

滑动窗口详解:解决无重复字符的最长子串问题
滑动窗口详解:解决无重复字符的最长子串问题 在算法面试中,“无重复字符的最长子串”问题是一个经典题目,不仅考察基础数据结构的运用,还能够反映你的逻辑思维能力。而在解决这个问题时,滑动窗口(Sliding …...

第05章 11 动量剖面可视化代码一则
在计算流体力学(CFD)中,动量剖面(Momentum Profiles)通常用于描述流体在流动方向上的动量分布。在 VTK 中,可以通过读取速度场数据,并计算和展示动量剖面来可视化呈现速度场信息。 示例代码 以…...

MySQL的复制
一、概述 1.复制解决的问题是让一台服务器的数据与其他服务器保持同步,即主库的数据可以同步到多台备库上,备库也可以配置成另外一台服务器的主库。这种操作一般不会增加主库的开销,主要是启用二进制日志带来的开销。 2.两种复制方式…...

Cpp::IO流(37)
文章目录 前言一、C语言的输入与输出二、什么是流?三、C IO流C标准IO流C文件IO流以写方式打开文件以读方式打开文件 四、stringstream的简单介绍总结 前言 芜湖,要结束喽! 一、C语言的输入与输出 C语言中我们用到的最频繁的输入输出方式就是 …...

基于OpenCV实现的答题卡自动判卷系统
一、图像预处理 🌄 二、查找答题卡轮廓 📏 三、透视变换 🔄 四、判卷与评分 🎯 五、主函数 六、完整代码+测试图像集 总结 🌟 在这篇博客中,我将分享如何使用Python结合OpenCV库开发一个答题卡自动判卷系统。这个系统能够自动从扫描的答题卡中提取信…...

如何将电脑桌面默认的C盘设置到D盘?详细操作步骤!
将电脑桌面默认的C盘设置到D盘的详细操作步骤! 本博文介绍如何将电脑桌面(默认为C盘)设置在D盘下。 首先,在D盘建立文件夹Desktop,完整的路径为D:\Desktop。winR,输入Regedit命令。(或者单击【…...

二十三种设计模式-享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,旨在通过共享相同对象来减少内存使用,尤其适合在大量重复对象的情况下。 核心概念 享元模式的核心思想是将对象的**可共享部分(内部状态)提取出来进行共…...

算法【有依赖的背包】
有依赖的背包是指多个物品变成一个复合物品(互斥),每件复合物品不要和怎么要多种可能性展开。时间复杂度O(物品个数 * 背包容量),额外空间复杂度O(背包容量)。 下面通过题目加深理解。 题目一 测试链接:[NOIP2006 提…...

A7. Jenkins Pipeline自动化构建过程,可灵活配置多项目、多模块服务实战
服务容器化构建的环境配置构建前需要解决什么下面我们带着问题分析构建的过程:1. 如何解决jenkins执行环境与shell脚本执行环境不一致问题?2. 构建之前动态修改项目的环境变量3. 在通过容器打包时避免不了会产生比较多的不可用的镜像资源,这些资源要是不及时删除掉时会导致服…...