题目:

给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例一:

输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]

示例二:

输入:nums = [0,1]
输出:[[0,1],[1,0]]

示例三:

输入:nums = [1]
输出:[[1]]

提示:

  • 1 <= nums.length <= 6
  • -10 <= nums[i] <= 10
  • nums 中的所有整数 互不相同

思路:

首先还是先来看题目,题目很简单明了,就是找齐全排列的情况,我们可以从提示中得到两点信息。1.nums数组长度最小为1,所以我们不需要对长度进行额外的判断。2.nums数组中的所有整数互不相同,这是很重要的一定。

题目看完了,我们很容易看出用回溯法来做这道题是最合适的,下面是我写的代码。

代码:

class Solution {
public:vector<vector<int>> res;vector<int> vec;set<int> _set;//标记集合void BackTracking(vector<int>& nums){if(vec.size() == nums.size()){//退出条件res.push_back(vec);return;}for(int i = 0; i < nums.size(); i++){//每一层选择if(_set.find(nums[i]) == _set.end()){//判断是否可以选择vec.push_back(nums[i]);_set.insert(nums[i]);BackTracking(nums);vec.pop_back();//回退到上一个状态_set.erase(nums[i]);}}}vector<vector<int>> permute(vector<int>& nums) {BackTracking(nums);return res;}
};

代码讲解:

vector<vector<int>> res;

vector<int> vec;

set<int> _set;//标记集合

首先这三个是我们在类中设置的变量,第一个res是一个二维数组,用来保存你最终要返回的答案的。第二个是一个一维数组,是我们用来存储每一个全排列的情况来使用的(这里我们使用vector数组的大容器与小容器的关系,我们直接将小容器(vec)装入大容器(res)中,就完成了二维数组的值的添加)。第三个是一个标记集合,标记集合我们在学习图的时候用到的非常多,这里的含义和在图中的含义是一样的,就是用力啊标记这个树是否已经加入到vec中。

vector<vector<int>> permute(vector<int>& nums) {

BackTracking(nums);

return res;

}

这就是主函数,没什么好说的,先调用了我们写的回溯函数,然后返回res数组。

void BackTracking(vector<int>& nums){

if(vec.size() == nums.size()){//退出条件

res.push_back(vec);

return;

}

for(int i = 0; i < nums.size(); i++){//每一层选择

if(_set.find(nums[i]) == _set.end()){//判断是否可以选择

vec.push_back(nums[i]);

_set.insert(nums[i]);

BackTracking(nums);

vec.pop_back();//回退到上一个状态

_set.erase(nums[i]);

}

}

}

接下来就是我们回溯的主要代码,首先我们先来讲一下代码,具体的流程我会放在下面。

首先先进来的if判断,用处就是回退的,和递归当中的一样,只不过这时我们完成小容器装入到大容器中这一步。

下面的for循环就是我们在写回溯时要用到的选择系统,我们如何去完成每一次选哪个数字技术通过for循环来完成的。

进入for循环当中,首先先从标记集合中判断当前数字是否已经放入vec中(学过图的同学应该对这个印象会很深),若没有放过,则进入if。

进入if,首先我们讲当前数字放入vec和标记集合当中,然后再次调用回溯函数 ,这里大体上和递归时一模一样的,区别就在于当回退到这里再向下运行函数时,我们完成的状态的回退,就是将vec和标记集合中的当前数字弹出,在弹出之后for循环i++,当前数字改变。

接下来我来给大家描述一下整个流程

这里我们拿示例一【1,2,3】来给大家讲

首先 permute函数调用了我们写的回溯函数,此时推出条件不成立,继续进行下面的代码,进入for循环当中,我们将1放入vec数组和_set标记集合中,然后再次调用回溯函数,(之后的回溯函数我们只说推出条件成立时的情况,不成立我们将不会赘述)进入for循环,此时i=0,nums[i]=1,标记集合当中查到了1已经存在了,所以i++,nums[i]=2,我们将2放入vec和标记集合中,再次调用回溯函数,1和2都在标记集合中存在了,所以3加入到vec和标记集合当中,再次调用回溯函数,此时满足退出条件,【1,2,3】的集合被装入到res中,回到上一层回溯

vec.pop_back();//回退到上一个状态

_set.erase(nums[i]);

我们使用这两条语句完成了状态的回退,将3从vec和标记集合中弹出,for循环结束,回退到上一层回溯,上一层回溯又将2从vec和标记集合中弹出,for循环的i++,此时nums[i]=3,将3加入到vec和标记集合当中,然后再次调用回溯函数,进入for循环发现1在标记集合中,所以将2加入vec和标记集合中,然后再次调用回溯函数,此时满足退出条件,【1,3,2】被装入到res当中,然后回退到上一层回溯,将2从vec和标记集合中弹出,for循环i++,nums[i] = 3,发现3已经在标记集合中了,for循环结束,回退到上一层循环,将3从vec和标记集合中弹出,for循环结束,将1从vec和标记集合中弹出,for循环i++,nums[i]=2,接下来就是和之前流程大差不差了,之不过是以2卡头了。

力扣46.全排列(回溯法)相关推荐

  1. 【LeetCode】46 全排列 回溯法三部曲模板+树枝节点去重

    因为确定leecode测试用例:-10 <= nums[i] <= 10,所以使用固定数组来代替unordered_set<> 进行树枝节点去重操作,减少一定的开销,同时相对来 ...

  2. 力扣46. 全排列(JavaScript)

    //遍历到叶子节点结束 var permute = function(nums) {let arr=[]let p=[]const dd=function(use){if(p.length==nums ...

  3. leetcode力扣46. 全排列

    给定一个没有重复数字的序列,返回其所有可能的全排列. 示例: 输入: [1,2,3] 输出: [   [1,2,3],   [1,3,2],   [2,1,3],   [2,3,1],   [3,1, ...

  4. 20210325:力扣递归,回溯类型题目合集

    力扣递归,回溯类型题目合集 题目 思路与算法 代码实现 写在最后 题目 子集 2. 90. 子集 II 3. 40. 组合总和 II 4. 22. 括号生成 思路与算法 子集:注释的很详细,递归生成子 ...

  5. 135. Leetcode 46. 全排列 (回溯算法-排列问题)

    class Solution:def permute(self, nums: List[int]) -> List[List[int]]:# 方法一# res = [] # 存放符合条件结果的集 ...

  6. 力扣78 77 46 子集、排列、组合 C++ 回溯法

    不同题目只需要解除相应的define注释即可 力扣78 子集 力扣77 组合 力扣46 全排列 #define SUBSET 1 // 子集//#define COMBINE 1 // 组合//#de ...

  7. 力扣刷题记录-回溯算法相关题目

    首先介绍一下回溯算法 回溯通常在递归函数中体现,本质也是一种暴力的搜索方法,但可以解决一些用for循环暴力解决不了的问题,其应用有: 1.组合问题: 例:1 2 3 4这些数中找出组合为2的组合,有1 ...

  8. 全排列【46. 全排列】

    一,题目描述 力扣 46. 全排列 难度中等1767 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 .你可以 按任意顺序 返回答案. 示例 1: 输入:nums = [1,2,3] ...

  9. 数据结构—回溯法、子集树、排列树

    文章目录 回溯法 问题的解空间 递归回溯 迭代回溯 子集树与排列树简单介绍 轮船装载问题 0-1背包问题 八皇后问题 整数求和(1) 整数求和(2) 全排列 回溯法 回溯法是一种以深度优先方式系统搜索 ...

最新文章

  1. 深入浅出统计学(十)抽取样本
  2. ECMA_作用域深入This关键字
  3. python零基础实例-零基础学习Python开发练习100题实例(1)
  4. 芜湖方特系统设计书php,芜湖方特梦幻王国
  5. 【Linux】7_存储管理基本分区
  6. Android中实现保存和读取文本文件到内部存储器(实现简易的记事本为例)
  7. 第二十五篇 hashlib模块(* *)
  8. 哀悼!知名教授逝世,享年55岁!
  9. TensorFlow 2快速入门之安装与测试
  10. C++中用TinyXML对XML文件进行解析
  11. 几种类型的db,以及最新的db排名,看一下
  12. 易支付v5.8个人二维码免签系统破解版
  13. 关于NuDaqPci 数据采集
  14. 用PHPphpstudy写一个可以登录的简单网页
  15. 网站备案需要什么材料
  16. 计蒜客_Lpl and Energy-saving Lamps_线段树
  17. @Transactional的readOnly、timeout
  18. 语法分析程序--编译原理
  19. 余弦相似度的计算方法
  20. hbase命令集(shell 命令,如建表,清空表,增删改查)

热门文章

  1. Python批量统计数据分布的偏度并画图
  2. 现代化养猪——养殖大数据
  3. 【Unity】LineRenderer画运动轨迹
  4. Ubuntu16.04安装qq和微信(亲测 可用)附安装包下载链接
  5. 《Electron 开发》 环境配置和Helloworld
  6. Python爬虫爬取微信朋友圈
  7. Win11下Clion+MSYS2(MinGW64)配置C++编译环境
  8. 【无标题】Java画板简易实现
  9. ios java模拟器 2017_Xcode9之更好用的iOS Simulator(模拟器)
  10. uniapp使用内置反馈建议,我方可客服实时回复功能