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

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

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

本篇建议收藏后食用~

题目:

OJ46:46. 全排列
OJ47:47. 全排列 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. 八、java操作swift对象存储(静态大对象)

    系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...

  2. uni-app图片上传接口联调

    https://www.bilibili.com/video/BV1jy4y1B7pw?p=159&spm_id_from=pageDriver

  3. nginx和前端

  4. 基于AHB_BUS Clac slave详解

    基于AHB-APB BUS slave详解 1.目录 高内聚:让模块的功能更集中,更单一. AMBA总线例子,需要有一个模块和AMBA进行交互,就可以单独将与AHB总线进行交互的部分作为一个模块.经常 ...

  5. 如何让golang的web服务热重载

    有很多方法可以热重载 golang Web 应用程序或 golang 程序. 我选择gin(不是web gin框架)来进行热重载. 首先在 GOPATH/bin下安装gin,命令如下所示: go ge ...

  6. 【MicroPython】要是找不到某个函数的定义,可能是做了宏转换

    转换宏 map查找接口

  7. .Net 使用 MongoDB

    1.安装nuget包 MongoDB.Driver 2.简单代码 using MongoDB.Bson; using MongoDB.Driver; using System.Buffers; usi ...

  8. [转帖]在Mysql中,什么是回表,什么是覆盖索引,索引下推?

    https://zhuanlan.zhihu.com/p/401198674 一.什么是回表查询? 通俗的讲就是,如果索引的列在 select 所需获得的列中(因为在 mysql 中索引是根据索引列的 ...

  9. [转帖]OceanBase 4.2.1 LTS 发版 | 一体化数据库首个长期支持版本

    2013.11.20 https://open.oceanbase.com/blog/7746655008?_gl=1*1qv10rf*_ga*Nzk3MjIxOTk0LjE3MDI2MTAxMzk. ...

  10. [转帖]paramiko简介

    https://www.cnblogs.com/qiujichu/p/12048763.html 一.什么是paramiko 要想明白什么是paramiko,要先明白ssh协议. 二.什么是ssh协议 ...