permutation:

在遇到全排列问题时,在数据量较小的情况下可以使用dfs的做法求得全排列,同时我们也知道在STL中存在函数next_permutation和prev_permutation,这两个函数可以较快的求出全排列,而这两个函数的实现却不是依赖于搜索算法(dfs)的。

分析:

以next_permutation为例,数据以1,2,3,4,5为例,对于一个排列我们知道其按照从小到大排序后的结果就是字典序最小的一个排列,而对于它的下一个排列为1,2,3,5,4比较这两个排列我们发现,排列的前三位没有改变,而最后两位发生了交换,原因是,对于一个排列而言他的从大到小排列(以下称倒序)为最后一个,因此对于倒序的排列,不存在下一个排列,而对于非倒序排列,一定存在下一个排列,因此对于1,2,3,4,5一定存在下一个排列。同时,为了找到他的下一个最小排列,我们应该尽可能保证前面的元素不变,改变最短的子序列达到下一个排列,所以我们从后向前找到第一个不满足逆序的位置即为4,之后,我们只需要找到在这个位置(这里是4)以后的这个子序列的下一个排列就可以了,4,5的下一个排列为5,4所以下一个排列为1,2,3,5,4。第三个排列为1,2,4,3,5。同之前的方法我们发现我们要寻找3,5,4的下一个排列,但是如果此时我们只是交换3和4的位置得到的4,5,3并不是他的下一个紧邻排列,我们观察发现,这样交换后,我们的到了4之后的序列的最大排列,但是因为我们的交换此时这个4处已经比上一排列的相同位置大了,而为了得到紧邻排列,我们需要将之后的子序列变换至最小排列,由最大排列变换至最小排列,我们只需要倒转这个序列就可。因此总结下来,从一个序列得到他的下一个紧邻排列,需要做:

  1. 从后向前查找第一个不满足倒序的位置ad
  2. 从后向前查找第一个大于ad处值的位置ch
  3. 交换ad和ch处的值
  4. 将ad+1到n的这个子序列倒转

代码实现:

#include<cstdio>
#include<cstring> void inline swap(char *s1,char *s2){
char t=*s1;
*s1=*s2;
*s2=t;
} void reverse(char *s,char* e){//反转s到e的子序列
for(e--;s<e;s++,e--)swap(s,e);
} bool next_permutation(char *start,char *end){
char *cur = end-1, *pre=cur-1;
while(cur>start && *pre>=*cur)cur--,pre--;//找到第一个不满足逆序的位置
if(cur<=start)return false; for(cur=end-1;*cur<=*pre;cur--);//找到逆序中大于*pre的元素的最小元素
swap(cur,pre);
reverse(pre+1,end);//将尾部的逆序变成正序
return true;
} int main(){
char s1[]="01224",s2[]="8000";
reverse(s1,s1+strlen(s1));
printf("%s\n",s1);
int n=strlen(s2);
puts("下一个排列:");
int cnt=0;
do{
puts(s2);
cnt++;
}while(next_permutation(s2,s2+n));
printf("%d",cnt);
}

例题:有重复元素的排列问题

题目描述:

设R={ r 1 , r 2 , …, r n }是要进行排列的n个元素。其中元素r 1 , r 2 , …, r n 可能相同。试设计一个算法,

列出R的所有不同排列。给定n 以及待排列的n 个元素。计算出这n 个元素的所有不同排列。

输入:

第1 行是元素个数n,1≤n≤500。接下来的1 行是待排列的n个元素。

输出:

计算出的n个元素的所有不同排列输出到文件perm.out中。文件最后1行中的数是排列总数。

样例输入:

4
aacc

样例输出:

aacc
acac
acca
caac
caca
ccaa
6

题解:

本题主要不要考虑重复元素,只需要改变实现代码中的比较符号即可。

/**********************************************************
* @Author: Maple
* @Date: 2020-02-22 17:47:36
* @Last Modified by: Maple
* @Last Modified time: 2020-02-22 18:52:34
* @Remark:
**********************************************************/
#include <bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define CSE(x,y) memset(x,y,sizeof(x))
#define INF 0x3f3f3f3f
#define Abs(x) (x>=0?x:(-x))
#define FAST ios::sync_with_stdio(false);cin.tie(0);
using namespace std; typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll , ll> pll; const int maxn=1000;
int n;
char str[maxn]; void swap(char &x,char &y){
char temp=x;
x=y;
y=temp;
return;
} void reverse(int l){
int i=0;
while(l+i<n-i){
swap(str[l+i],str[n-i]);
i++;
}
return;
} bool next_permutation(){
int ad=n-1;
//找到第一个不为逆序的元素
for(ad;str[ad]>=str[ad+1];ad--);
if(!(ad>0))
return false;
int ch=n;
//找到第一个
for(ch;str[ch]<=str[ad];ch--);
swap(str[ad],str[ch]);
reverse(ad+1);
return true;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
#endif
cin>>n;
cin>>str+1;
sort(str+1,str+1+n);
int ans=0;
do{
puts(str+1);
ans++;
}while(next_permutation());
cout<<ans<<endl;
return 0;
}

STL中的全排列实现的更多相关文章

  1. STL中关于全排列next_permutation以及prev_permutation的用法

    这两个函数都包含在algorithm库中.STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和prev_permutation. 一.函数原型 首先我们来看看这两个函数 ...

  2. hdu1027 Ignatius and the Princess II (全排列 &amp; STL中的神器)

    转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=1027 Ignatiu ...

  3. STL中的next_permutation

    给定一个数组a[N],求下一个数组. 2 1 3 4 2 1 4 3 2 3 1 4 2 3 4 1 ..... 在STL中就有这个函数: 1.参数是(数组的第一个元素,数组的末尾),注意这是前闭后开 ...

  4. STL中的set容器的一点总结

    1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...

  5. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  6. C++的模板特化 和 STL中iterator_traits模板的偏特化

    C++中有类模板和函数模板,它们的定义如下所示: 类模板: template<class T1,class T2> class C { //... }; 函数模板: template< ...

  7. C++的STL中vector内存分配方法的简单探索

    STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux  CentOS 5.2 1.代码 #include <vector> #include <stdio ...

  8. C++ STL中vector(向量容器)使用简单介绍

    原文:http://www.seacha.com/article.php/knowledge/cbase/2013/0903/2205.html C++ vector(向量容器)是一个线性顺序结构.相 ...

  9. 深入了解STL中set与hash_set,hash表基础

    一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(l ...

随机推荐

  1. Java面向对象编程 -1.6

    引用传递与垃圾产生分析 经过了一系列的分析之后已经确认,所有的引用传递的本质就是一场堆内存的调戏游戏.如果对于引用传递如果处理不当那么也会造成垃圾的产生, 那么本次将针对于垃圾产生的原因进行简单分析. ...

  2. IIS7和IIS8环境下 ThinkPHP专用URL Rewrite伪静态规则

      这是适用于IIS7,IIS7.5,IIS8.0及以上的ThinkPHP的伪静态规则,把以下代码保存成web.config文件,放到FTP的web目录内即可. <?xml version=&q ...

  3. SpringBoot与Mybatis-plus整合,代码生成mvc层

    一.添加pom依赖 <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifac ...

  4. 微信小程序 列表倒计时

    最近要实现一个列表倒计时的功能,写了个demo 展示图 <view class="center colu"> <view class="time&quo ...

  5. Java面向对象编程 -1

    面向对象简介 C语言是面向过程开发的代表 C++ 或者Java 是面向对象的编程语言 所谓的面向过程指的是面对于一个问题的解决方案,更多的情况下是不会做出重用的设计思考的. 而面向对象的主要设计形式是 ...

  6. Lora笔记

    Lora笔记 2016-03-26 [概述] LPWAN技术 无线跳频技术简介 https://bitbucket.org/ [节点] SX1278测试 SX1278测试 SX1276调试总结 LoR ...

  7. Linux centosVMware 自动化运维认识自动化运维、启动salt相关服务、saltstack配置认证、salt-key命令用法、saltstack远程执行命令、saltstack - grains、saltstack – pillar

    一.认识自动化运维 传统运维效率低,大多工作人为完成 传统运维工作繁琐,容易出错 传统运维每日重复做相同的事情 传统运维没有标准化流程 传统运维的脚本繁多,不能方便管理 自动化运维就是要解决上面所有问 ...

  8. Redis 的使用

    1. 概念: redis是一款高性能的NOSQL系列的非关系型数据库 1.1.什么是NOSQL NoSQL(NoSQL = Not Only SQL),意即"不仅仅是SQL",是一 ...

  9. Django 学习之cookie与session

    一.cookie和session的介绍 cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生. cookie ...

  10. 设计模式课程 设计模式精讲 7-3 建造者模式源码解析(jdk+guava+spring+mybaties)

    1 源码解析 1.1 jdk解析 1.2 guava解析 1.3 spring解析 1.4 mybaties解析 1 源码解析 1.1 jdk解析 String public StringBuilde ...