【算法】【回溯】两道经典排列问题OJ详解【力扣46 力扣47】【超详细的回溯算法教程】让我们牢牢把握回溯的精髓

作者: @小小Programmer
这是我的主页:@小小Programmer
在食用这篇博客之前,博主在这里介绍一下其它高质量的编程学习栏目:
数据结构专栏:数据结构 这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏:算法 这里可以说是博主的刷题历程,里面总结了一些经典的力扣上的题目,和算法实现的总结,对考试和竞赛都是很有帮助的!
力扣刷题专栏Leetcode想要冲击ACM、蓝桥杯或者大学生程序设计竞赛的伙伴,这里面都是博主的刷题记录,希望对你们有帮助!

先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一种非常重要的动力。看完之后别忘记关注我哦!️️️

本篇建议收藏后食用~

题目:

OJ4646. 全排列
OJ4747. 全排列 II

OJ46 全排列

题目描述

实现思路

首先,这两道题我们肯定是要用回溯实现的,我们要通过回溯,来找到每一种排列方式。
因此,在这里,博主先带着大家复习一下回溯算法的精髓

回溯算法的三部曲:

  1. 确定递归函数参数和返回值
  2. 确定递归终止条件
  3. 确定单层递归逻辑

一:确定递归函数的参数和返回值
这里和组合问题是不一样的,因为排列问题是有顺序可言的,比如例题一:我们要找[1,2,3]的排列,第二次从2开始找的时候,前面的1也是要进去的,即[1,2..][2,1...]是不同的排列,因此,我们的递归函数除了原来的数组之外,还需要一个数组来记录,哪一个数字已经用过了。 比如第一个数字挑了2,即[2,...],此时,第二个数字的选择只能是1或者3,因为2已经用过了。
所以我们的递归函数:

void backtracking(vector<int>& nums, vector<bool>& used)

当然,我们还需要创建全局的两个数组,一个用来做最后结果的收集,一个用于递归回溯。

vector<vector<int>>ret;
vector<int>path;

二:确定递归终止条件
很明显,当递归数组(path)满了的时候,就终止递归。
比如:求[1,2,3]的排列,当一个数组path[]收集到3个数的时候,就要返回了,比如path里面是[2,1,3]的时候,如果只有两个或者一个数,递归就要继续。

        if (path.size() == nums.size()) {
ret.push_back(path);
return;
}

三. 确定单层递归逻辑
当然,单层搜索就是递归了

  • 递归回溯永不分离
  • 一次递归伴随着一次回溯

所以我们每次递归完一定要记得撤销,回溯。

完整代码

//OJ46 全排列
class Solution {
private:
vector<vector<int>>ret;
vector<int>path;
void backtracking(vector<int>& nums, vector<bool>& used) {
//此时说明找到了一组结果
//2.终止条件
if (path.size() == nums.size()) {
ret.push_back(path);
return;
}
//3.单层搜索
for (int i = 0; i < nums.size(); i++) {//每次都要从头开始搜索
if (used[i] == true)continue;//如果这个数字用过了,直接跳过本次循环
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
//撤销,回溯
path.pop_back();
used[i] = false;
}
}
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<bool>used(nums.size(), false);
backtracking(nums, used);
return ret;
}
}; /*
* 和组合问题的区别
* 每层都是从0开始搜索,而不是从startIndex开始搜索---[1,2]中用过1了,但是[2,1]中还得用1
* 需要used数组记录path中都存放了哪些元素
*/
//used是用来防止同一个数选两次的

OJ47 全排列ll

题目描述

实现思路

这其实就是一个经典的去重问题,方法同样是用used数组来完成去重

要注意的点:

  • 去重之前要对数组进行排序,要将一样的数字放在一起
  • 去重的判断条件,当当前下标所对应的数和前一个下标所对应的数一致,并且这个数并不是在同一个树枝上时去重

一:确定递归函数的返回值和参数

void backtracking(vector<int>& nums, vector<bool>& used)

二:确定递归的终止条件,这些都和前面一样的。

        if (path.size() == nums.size()) {
ret.push_back(path);
return;
}

三:确定单层搜索逻辑:

  • 具体的去重实现,请看完整代码的注释,若还有不明白的,可以私信博主噢! 其实这个去重思路是非常经典的思路,是必须要掌握的!

完整代码

class Solution {
private:
vector<vector<int>>ret;
vector<int>path;
void backtracking(vector<int>& nums, vector<bool>& used) {
if (path.size() == nums.size()) {
ret.push_back(path);
return;
}
for (int i = 0; i < nums.size(); i++) {
if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false)continue;//首先一定要i>0,保证这不是这棵树的根节点
//nums[i]==nums[i-1]说明可能会出现重复,但是此时不确定是这两个相同的数出现在同一树层上还是同一树枝上
//如果实在同一树枝上,是可以的,比如在[1,1,2]是没问题的
//但是如果是在同一树层上是不行的,可能会出现重复
//所以used[i-1]=false 保证这是在同一树层上的,而不是同一树枝上的
if (used[i] == false) {
used[i] = true;
path.push_back(nums[i]);
backtracking(nums, used);
path.pop_back();
used[i] = false;
}
}
}
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<bool>used(nums.size(), false);
backtracking(nums, used);
return ret;
}
};
//为什么去重的时候写第二个&&左边写
//used[i-1]==false;或used[i-1]=true;都可以呢?
//因为在树枝上去重和在树层上去重都可以的
//在树层上去重的效率很高,
//在树枝上去也可以,但是做了很多无用的搜索

尾声

看到这里相信你对排列问题的这两道OJ已经有一定的理解了,其实排列问题是一个非常经典的我们必须要掌握的问题。
在走之前,可以再看看博主的这些专栏内容对你是否有帮助: 有的话请不要吝啬你们的点赞收藏关注和转发噢!

数据结构专栏:数据结构 这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏:算法 这里可以说是博主的刷题历程,里面总结了一些经典的力扣上的题目,和算法实现的总结,对考试和竞赛都是很有帮助的!
力扣刷题专栏Leetcode想要冲击ACM、蓝桥杯或者大学生程序设计竞赛的伙伴,这里面都是博主的刷题记录,希望对你们有帮助!

【算法】【回溯】两道经典排列问题OJ详解【力扣46 力扣47】【超详细的回溯算法教程】让我们牢牢把握回溯的精髓的更多相关文章

  1. 【转载】NeurIPS 2018 | 腾讯AI Lab详解3大热点:模型压缩、机器学习及最优化算法

    原文:NeurIPS 2018 | 腾讯AI Lab详解3大热点:模型压缩.机器学习及最优化算法 导读 AI领域顶会NeurIPS正在加拿大蒙特利尔举办.本文针对实验室关注的几个研究热点,模型压缩.自 ...

  2. PHP用strtotime()函数比较两个时间的大小实例详解

    在PHP开发中,我们经常会对两个时间的大小进行判断,但是,在PHP中,两个时间是不可以直接进行比较,因为时间是由年.月.日.时.分.秒组成的,所以,如果需要将两个时间进行比较的话,我们首先要做的就是将 ...

  3. BM算法  Boyer-Moore高质量实现代码详解与算法详解

    Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...

  4. 【转】小波与小波包、小波包分解与信号重构、小波包能量特征提取 暨 小波包分解后实现按频率大小分布重新排列(Matlab 程序详解)

    转:https://blog.csdn.net/cqfdcw/article/details/84995904 小波与小波包.小波包分解与信号重构.小波包能量特征提取   (Matlab 程序详解) ...

  5. openerp经典收藏 字段定义详解(转载)

    字段定义详解 原文地址:http://shine-it.net/index.php/topic,2159.0.htmlhttp://blog.sina.com.cn/s/blog_57ded94e01 ...

  6. openerp经典收藏 对象定义详解(转载)

    对象定义详解 原文地址:http://shine-it.net/index.php/topic,2159.0.htmlhttp://blog.sina.com.cn/s/blog_57ded94e01 ...

  7. 一个经典的 HTTP协议详解

    1引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展.目前在WWW中使用的是HTTP/1 ...

  8. 二分算法题目训练(三)——Anton and Making Potions详解

    codeforces734C——Anton and Making Potions详解 Anton and Making Potions 题目描述(google翻译) 安东正在玩一个非常有趣的电脑游戏, ...

  9. [转]从两道经典试题谈C/C++中联合体(union)的使用

    宋宝华 21cnbao sweek@21cn.com 试题一:编写一段程序判断系统中的CPU是Little endian还是Big endian模式? 分析: 作为一个计算机相关专业的人,我们应该在计 ...

  10. 看到两道小学数学题,实在是解不动,用js写了一下

    把一个自然数的约数(除去它本身)按照从小到大的顺序写在它的左边,可以得到一个多位数,比如6的约数是1,2,3,写成一个多位数是1236,假如这个多位数中,没有直复数字,那么我们你这个多位数是唯一的.请 ...

随机推荐

  1. html5 video视频,本地环境好的,线上环境,不能播放

    本地环境ok,发布到线上不能播放.之前看这个视频,把video放在public文件夹下的. 后来经过排查,video放public文件夹下,导致的.应该放assets里. 后来,和同事讨论,线上服务器 ...

  2. 启动vue项目失败,报错Failed at the node-sass@4.14.1 postinstall script.

    https://www.cnblogs.com/xiaodangshan/p/13061618.html

  3. Linux telnet安装及端口测试联通性

    安装步骤: 可使用该文中的步骤进行安装,已经过本人验证,是可以安装成功的: https://blog.csdn.net/doubleqinyan/article/details/80492421 安装 ...

  4. C语言中的操作符:了解与实践

    ​ 欢迎大家来到贝蒂大讲堂 ​ 养成好习惯,先赞后看哦~ ​ 所属专栏:C语言学习 ​ 贝蒂的主页:Betty's blog 1. 操作符的分类 操作符又叫运算符,它在C语言中起着非常大的作用,以下是 ...

  5. 【css】 text-align 居中导航

    原理 :利用 inline-block 将 导航 作为 文本 , 被外层具有 text-align 属性的导航盒子包含 .从而实现居中效果 1.  html 结构 <header> < ...

  6. Go——语言特性

    golang 简介 来历 很久以前,有一个IT公司,这公司有个传统,允许员工拥有20%自由时间来开发实验性项目.在2007的某一天,公司的几个大牛,正在用c++开发一些比较繁琐但是核心的工作,主要包括 ...

  7. [转帖]clickhouse 超底层原理& 高可用集群 实操(史上最全)

    https://www.cnblogs.com/crazymakercircle/p/16718469.html 文章很长,而且持续更新,建议收藏起来,慢慢读!疯狂创客圈总目录 博客园版 为您奉上珍贵 ...

  8. drop_caches 的简单学习

    drop_caches 的简单学习 背景 最近一段时间一直在学习内存相关的知识 Linux系统里面的内存管理还是非常复杂的. 我这边理解 Linux从宏观层次的 段页式内存管理 到细节的buddy和s ...

  9. [转帖]goproxy 使用说明

    Go 版本要求 建议您使用 Go 1.13 及以上版本, 可以在这里下载最新的 Go 稳定版本. 配置 Goproxy 环境变量 Bash (Linux or macOS) export GOPROX ...

  10. [转贴]细说:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4

    细说:Unicode, UTF-8, UTF-16, UTF-32, UCS-2, UCS-4 https://www.cnblogs.com/malecrab/p/5300503.html 1. U ...