AcWing 51. 数字排列(DFS(有重复排列+无重复排列))

AcWing刷题1 一、前言 最近发现一个算法题目的宝藏平台,上面的题目其实都是比较偏向应用题了,所以可能更适合用来提高自己笔试的能力。在这里还没有入口的uu们可以在这里看一看哦:AcWing刷题网站 今天其实做了上周的周赛的一个题目,才发现自己很多基础的算法模板都没有掌握,所以只能说我算法还是没有真正的入门吧!今天其实也少稍微的学习了一下,关于区间合并的一个模板问题,题目描述如下: 二、题目描述 三、思路 本题的思路需要一些推导,也不是特别难,我们可以看到假设a数组中的ai=aja_i = a_jai​=aj​的话,那么由 阅读详情

OJ上这道题的描述并不清晰。实际上,它的要求是输出所有“不重复的排列方式”。

1.next_permutation()(无重复排列)

要解决数组无重复排列的问题,那么这个方法是再合适不过的了。在使用这个函数前注意要引入<algorithm>头文件并且为了保证可以枚举所有情况要实现对数组进行“由小到大”的排序。

具体代码如下:

class Solution {
public:
    vector<vector<int>> permutation(vector<int>& nums) {
        vector<vector<int>> ans;
        sort(nums.begin(), nums.end());
        do{
            ans.push_back(nums);
        }while(next_permutation(nums.begin(), nums.end()));
        return ans;
    }
};

2.DFS(有重复排列(交换+循环遍历))

这里提供两种思路。

首先是交换。可以将整个数组分成两部分:第一个元素和其他元素。求全排列的过程可以看成两个子过程,一个是确定首元素,另一个是确定剩余元素的全排列(其中,如果确定的首元素不是nums[0],则交换该元素和nums[0])。显然,剩余元素全排列的求解就是递归执行以上过程。

具体代码如下:

class Solution {
public:
    void dfs(vector<vector<int>> &ans, vector<int> nums, int cur){
        if(cur == nums.size()) {
            ans.push_back(nums);
            return;
        }
        for(int i = cur; i < nums.size(); i++){
            swap(nums[cur], nums[i]); //通过交换方式将首元素放置到起始位置
            dfs(ans, nums, cur + 1);
        }
    }
    
    vector<vector<int>> permutation(vector<int>& nums) {
        vector<vector<int>> ans;
        dfs(ans, nums, 0);
        return ans;
    }
};

第二种思路就是循环遍历。利用标记数组记录每一个原数组中的元素是否被访问到,根据递归加循环遍历的次序依次将元素插入中间结果数组中。当递归到达出口时将中间结果存入最终结果当中。

具体代码如下:

class Solution {
public:
    vector<vector<int>> ans; //存放最终结果
    vector<int> temp; //存放中间结果
    vector<int> mark; //标记数组

    void dfs(vector<int> &nums, int cur){
        if(cur == nums.size()) {
            ans.push_back(temp);
            return;
        }
        for(int i = 0; i < nums.size(); i++){
            if(!mark[i]){
                mark[i] = 1;
                temp[i] = nums[cur];
                dfs(nums, cur + 1);
                mark[i] = 0;
            }
        }
    }
    
    vector<vector<int>> permutation(vector<int>& nums) {
        temp.resize(nums.size());
        mark = vector<int> (nums.size(), 0);
        dfs(nums, 0);
        return ans;
    }
};

需要特别说明的是:虽然两份代码中的函数参数完全一致,但是其中cur的含义并不相同!第一份代码中的cur指的是确定好结果数组首元素后剩余子数组的起始位置。而第二份代码中的cur则指的是将要判断是否要插入到结果数组中的元素在原数组中的位置。

如果从时空复杂度的角度上来看,后者的复杂度无论在时间还是空间上均要高于前者。不过,后者的方法比前者更容易扩展到无重复排列的情况!

3.DFS(无重复排列)

核心思路与有重复排列的思想一致,需要额外考虑就是如何去重。可以考虑将每一次的结果进行记录,如果后面有遇到已经保存过的结果则直接跳过(由于思路比较简单且时空复杂度较高,这里不再提供代码)。或者还可以根据DFS具有回溯的性质,对已经使用的原数组的元素进行标记。这里提供两种不同的标记方法,其中一种使用了规模与原数组相同的标记数组,另一种则采用二进制的方式来记录每个元素的标记情况。这两种方法都是从有重复排列的第二种思想的代码上扩展得来的。

该方法大致的思路是:首先对原数组进行排序操作从而让所有相同的元素相邻;在原算法的基础上新增一个变量start用来记录当前递归中循环选择元素的起始位置。(对于有重复排列而言,start是恒为0的。实际上这也正是会产生重复排列的原因);如果说当前元素与下一个要判断是否加入到结果中的元素不同,则不做任何修改,仍然按照原来的有重复算法执行。但是如果当前元素与下一个要判断是否加入到结果中的元素相同,则下一层递归的遍历就要从当前递归所加入的元素在原数组中的位置的下一个位置(也就是i+1)开始。

具体代码如下:

class Solution {
public:
    vector<vector<int>> ans; //存放最终结果
    vector<int> temp; //存放中间结果
    vector<int> mark; //标记数组

    void dfs(vector<int> &nums, int cur, int start){
        if(cur == nums.size()) {
            ans.push_back(temp);
            return;
        }
        for(int i = start; i < nums.size(); i++){
            if(!mark[i]){
                mark[i] = 1;
                temp[i] = nums[cur];
                if(cur + 1 < nums.size() && nums[cur] != nums[cur + 1])
                    dfs(nums, cur + 1, 0);
                else
                    dfs(nums, cur + 1, i + 1);
                mark[i] = 0;
            }
        }
    }
    
    vector<vector<int>> permutation(vector<int>& nums) {
        temp.resize(nums.size());
        mark = vector<int> (nums.size(), 0);
        sort(nums.begin(), nums.end());
        dfs(nums, 0, 0);
        return ans;
    }
};

另外,还可以用二进制的方式来存放原数组中元素的访问信息。二进制由低到高分别记录原数组从头到尾的元素的访问情况。1代表已访问,0代表未访问。

具体代码如下:

class Solution {
public:
    vector<vector<int>> ans; //存放最终结果
    vector<int> temp; //存放中间结果
    
    void dfs(vector<int> &nums, int cur, int start, int state){
        if(cur == nums.size()) {
            ans.push_back(temp);
            return;
        }
        for(int i = start; i < nums.size(); i++){
            if(!(state >> i & 1)){
                temp[i] = nums[cur];
                if(cur + 1 < nums.size() && nums[cur] != nums[cur + 1])
                    dfs(nums, cur + 1, 0, state + (1 << i));
                else
                    dfs(nums, cur + 1, i + 1, state + (1 << i));
            }
        }
    }
    
    vector<vector<int>> permutation(vector<int>& nums) {
        temp.resize(nums.size());
        sort(nums.begin(), nums.end());
        dfs(nums, 0, 0, 0);
        return ans;
    }
};

 

有重复元素的排列问题 Description 设集合R={r1,r2,...,rn}是要进行排列的n个元素,其中r1,r2,...,rn可能相同。 试着设计一个算法,列出R的所有不同排列。 即,给定n以及待排的n个可能重复的元素。计算输出n个元素的所有不同排列。 输入格式 第1行是元素个数n,1<=n<=15。接下来的1行是待排列的n个元素,元素中间不要加空格。 输出格式 程序运行结束时,将计算输出n个元素的所有不同排列。最后1行中的数是排列总数。 立即下载

相关推荐

树莓派4B+红外传感器:手把手教你DIY一个能走黑线的智能小车(Python代码全解析)

本文详细介绍了如何使用树莓派4B和红外传感器DIY一个智能循迹小车,包括硬件配置、GPIO连接、Python代码实现及优化算法。通过动态PWM调速、状态机设计和赛道记忆算法,提升小车的循迹性能和稳定性。适合初学者和电子爱好者动手实践。

weixin_29188043的博客 269

刷题网站

1. 力扣(这个网站中题解真的是非常丰富,适合新手刷题,不会的可以看看题解) 英文网址:https://leetcode.com/ 中文网址:https://leetcode-cn.com/ 2.hihoCoder 网址:https://hihocoder.com/ 3. 牛客网(题目质量还是ok的) 网址:https://www.nowcoder.com/ 4. 计蒜客(适合ACM竞赛) 网址:https://www.jisuanke.com/ 5. HDU 6. POJ 7.Co..

二哈 1万+

InfiniBand(IB)实战指南:从硬件配置到性能优化

本文是一份详尽的InfiniBand实战指南,涵盖从硬件选型、部署到驱动配置、性能优化的全流程。重点解析了InfiniBand作为AI训练与高性能计算(HPC)核心网络的优势,特别是其支持的RDMA技术如何实现微秒级低延迟。文章提供了硬件匹配、NCCL压测、内核参数调优及在PyTorch分布式训练中启用IB的实操步骤,旨在帮助工程师构建和优化高性能计算集群。

mqtt6iot的博客 581

ACwing算法基础课——基础算法

算法基础课复习

astruggle___的博客 2502

荔枝派Lichee Nano全志F1C100s烧录避坑指南:从Fel模式到SPI Flash完整流程

本文详细介绍了荔枝派Lichee Nano基于全志F1C100s芯片的SPI Flash烧录完整流程,从FEL模式进入技巧到定制化sunxi-tools编译,再到分区策略与实战烧录步骤。针对开发者常见的烧录程序问题提供了专业解决方案,帮助用户高效完成嵌入式系统部署。

tea88的博客 788

Wireshark教程:解密HTTPS流量

Wireshark教程:如何解密HTTPS流量

nuan444979的博客 1万+

Acwing - 算法基础课 - 笔记(数据结构 · 一)

文章目录数据结构(一)链表栈和队列单调栈单调队列KMP算法 数据结构(一) 本节讲解的是 链表与邻接表 栈与队列 看毛片(kmp)算法 链表 使用数组模拟单链表,双链表 使用数组模拟的链表,为静态链表,对单链表,开2个数组,其中1个用来存每个链表节点的值,另1个数组用来存每个节点的next指针。 对双链表,开3个数组,其中1个用来存每个链表节点的值,另外2个数组用来存每个节点的prev和next指针 单链表,用到比较多的是邻接表,邻接表经常用来存储图和树。(会在后续第三章讲图论时带出) 单链表练习题:A

vcj1009784814的博客 2052

从静态到动态:如何用Deformable 3DGS和4DGS实现高效动态场景建模

本文深入探讨了Deformable 3DGS和4DGS在动态场景建模中的技术突破,详细解析了这两种方法如何高效处理动态内容。Deformable 3DGS通过引入时间维度的变形场扩展传统3DGS,而4DGS则采用四维时空体素分解方法,两者均显著提升了动态场景建模的效率和质量,适用于虚拟现实、增强现实等应用场景。

weixin_29063035的博客 433

AcWing食用指南

​ AcWing是一个计算机编程相关知识学习网站,其中有算法课程与工程课程。适合计算机相关专业以及想要从事计算机相关专业工作的同学食用。这是一个很适合学习算法的平台,学习过程非常平滑,适合所有阶段的同学。

DM010maker的博客 7618

蓝桥杯第七届省赛试题--“模拟风扇控制系统”

题目要求 功能简述 “模拟风扇控制系统”能够模拟电风扇工作,通过按键控制风扇的转动速度和定时时间,数码管实时显示风扇的工作模式,动态倒计时显示剩余的定时时间,系统主要由数码管显示、单片机最小系统、按键输入和电机控制保护电路组成,系统框图如图 1 所示: 单总线驱动程序、CT107D 单片机考试平台电路原理图以及本题所涉及到的芯片数据手册,可参考计算机上的电子文档。程序流程图及相关工程文件请以考生...

qq_43280087的博客 2659

Python爬虫案例——解密抓取西红柿小说《我不是戏神》全章节!!!

本文介绍了抓取番茄小说网站《我不是戏神》全本内容的完整流程。首先分析网站反爬机制,发现采用自定义混淆字体加密文本内容。通过下载字体文件并解析字符映射关系,组建本地字体映射表。随后编写Python爬虫程序,实现自动获取章节链接、请求加密内容、解密替换字体、保存为本地txt文件等功能。代码包含UA伪装、请求头设置、进度条显示等细节处理,最终实现小说内容的完整抓取与解密存储。

@优快云盲敲代码的阿豪的博客 660

Acwing dfs+回溯专题题解

17-电话号码的字母组合 其实就是map那个感觉有点麻烦,其他还行 46-全排列 next_permutation函数,产生所有的下一个组合,所以要先升序排序,保证能有所有下一组合 全排列II next_permutation就是返回不重复的,所以可以继续使用 ...

qq_48344603的博客 415

Unity如何实现3D物体拆解组装

最近有一个需求,是做一个发动机的拆卸和安装功能,其实是一个很简单的功能,但是其中有一个点我觉的非常有意思,就是拖拽组装时,物体如何精准拖到目标位置,思路有了,但是我一直找不到实现方式,早晨刷牙时无意间想到了叉乘,我才有了解决方案。就凭这一次的灵光乍现,也很有必要写篇博客来记录一下。首先,我们先来看下我们要实现的效果,就是对一个发动机(任意多组件物体,如:车)的360°预览查看,手动拖拽拆解,手动拖拽组装。360°旋转视角远近拉伸视角点击拖拽拆卸拖拽组装。

TxNet 1万+

2026csp-j初赛必记代码

【代码】csp j初赛必记代码。

qq_36107829的博客 468

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

全排列算法(无重复数字全排列/有重复数字全排列)/ 组合算法/ 求子集算法

无重复/有重复数字全排列相关算法

weixin_43281875的博客 1万+

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

AcWing

About AcWing

良月澪二的博客 4600

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

信息学竞赛有什么好的比赛网站?

1、HustOJ MYOJ 热心家长创建的一个自测 OJ,与华中科技大学颇有渊源。不定期举办一些针对初学者的比赛。菜鸟们不妨一试。 2、信奥题库 信奥题库https://www.oitiku.com/ 3、计蒜客 www.jisuanke.com 课程要付费,但是月赛和题库是免费的,判题速度快,手感还不错 计蒜客比赛 比赛 - 计蒜客计蒜客比赛平台为广大选手提供ACM、ICPC网络赛,NOIP普及组和提高组模拟赛,蓝桥杯省赛、国赛模拟赛,并承接各种商业比赛,是竞赛党练习、参赛的专业

青少年趣味编程 1万+

一键授权登录

该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数(如果是将第三方授权登录绑定到现有账号上,那么推荐用随机数 + user_id作为state的值,可以有效防止CSRF攻击)access_token的有效期为2小时,时间较短。请求地址:https://www.acwing.com/third_party/api/oauth2/access_token/如果access_token未过期,则将当前的access_token的有效期延长为2小时。

m0_59519985的博客 821

51. 数字排列

输入一组数字(可能包含重复数字),输出其所有的排列方式

一个字,学 305

Acwing-51. 数字排列

3、对于相同数,我们人为定序,就可以避免重复计算:我们在dfs时记录一个额外的状态,记录上一个相同数存放的位置 start,我们在枚举当前数时,只枚举 start+1,start+2,…,nstart+1,start+2,…由于有重复元素的存在,这道题的枚举顺序和 Permutations 不同。1、先将所有数从小到大排序,这样相同的数会排在一起;2、从左到右依次枚举每个数,每次将它放在一个空位上;4、不要忘记递归前和回溯时,对状态进行更新。

青衫客36的博客 286

推荐资源:算法、刷题网站

开始刷题之旅,推荐给大家几个网站,Joy自己也Mark一下: 1,AcWing 网址,北大几个牛人创建的程序员刷题网站,良心首选。yxc大牛的空间附上,有宝藏!!! 2,LeetCode 乐扣,刷题网址,一起刷题!!! 3,牛客网 经典刷题网址,刷题、笔试必备啊! 4,剑指offer,网址,网上试题资源,一起做offer收割机!!! 附上GitHub上的程序代码,cli...

Joye-joy的博客 4602

【数学建模】【python】有重复全排列和无重复全排列

排列和全排列的定义 类似于高中里的排列组合,从 n 个不同的元素中取出 m (m <= n) 个元素,按照一定的顺序排列从中取出的 m 个元素,叫一个排列。 当 m = n 时,也就是对这 n 个元素进行排列的时候,这个排序被称为全排列。 无重复全排列 无重复全排列即在排列中没有重复元素。 例如:求‘abc’ 的无重复全排列,为: 重复全排列 这里给出的 ‘abc’ 没有重复元素,倘若给出的是 ‘abb’ ,就变成了有重复全排列。 首先,它的全排列共有 6 种: 再通过筛选,将其中重复的数进行剔除

m0_53347750的博客 1593

【ACWing】51. 数字排列

题目地址: https://www.acwing.com/problem/content/47/ 输入一组数字(可能包含重复数字),输出其所有的排列方式。 参考https://blog.csdn.net/qq_46105170/article/details/104890873。代码如下: #include <vector> using namespace std; class Solution { public: vector<vector<int>> per

数学、算法爱好者的博客 172

【算法基础】DFS深度优先算法 —— AcWing 843. n-皇后问题 AcWing 842. 排列数字

Acwing算法基础课笔记 题解 AcWing 843. n-皇后问题 AcWing 842. 排列数字

Remember who you are! 5426

没有重复项数字的全排列

题目 描述 给出一组数字,返回该组数字的所有排列 例如: [1,2,3]的所有排列如下 [1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2], [3,2,1]. (以数字在数组中的位置靠前为优先级,按字典序排列输出。) 数据范围:数字个数 0<n≤6 要求:空间复杂度 O(n!) ,时间复杂度 O(n!) 思路 全排列的问题直接使用深度优先遍历 代码 python版本: # # 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 # # # @para

weixin_41803339的博客 1035

可重复全排列与不可重复全排列

全排列定义 排列,一般地,从n个不同元素中取出m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列(permutation)。 特别地,当m=n时,这个排列被称作全排列(all permutation)。 可重复全排列 可重复全排列即在排列中会有重复元素。下面是全排列的递归写法: 假设我们有数组a[5]={3, 4, 5, 6, 7},且我们想知道这个数组的全部排列。 我们可以从第零位开始与后面所有位进行交换,交换完递归下一层,下一层从第一位开始与后面所有位交换。这样知道递归到

three_trees的blog 4175
上一篇: AcWing 49. 二叉搜索树与双向链表(前驱后继+中序遍历)
下一篇: AcWing 52. 数组中出现次数超过一半的数字(基于中位数和众数的线性复杂度的解法)
Zee_Chao
博客等级 码龄11年 168粉丝 135原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值