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. 杭电2602 Bone Collector

    Bone Collector Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  2. 【原】python总结

    python3浅拷贝和深拷贝:https://www.jianshu.com/p/c7e72fcad407

  3. leetcode 0216

    目录 ✅ 893. 特殊等价字符串组 描述 解答 cpp py ✅ 811. 子域名访问计数 描述 解答 cpp py ✅ 509. 斐波那契数 描述 解答 cpp py ✅ 521. 最长特殊序列 ...

  4. apache 配置虚拟目录

    #注释掉apache默认的网站目录地址 #DocumentRoot "c:/Rrogram Files/Apache/htdocs" #配置一个虚拟目录 <ifModule ...

  5. Trie学习总结

    Trie树学习总结 字典树,又称前缀树,是用于快速处理字符串的问题,能做到快速查找到一些字符串上的信息. 另外,Trie树在实现高效的同时,会损耗更多的空间,所以Trie是一种以空间换时间的算法. T ...

  6. CSS选择器整理

    基本选择器 标签选择器:直接写标签名 id选择器:#id名 class选择器:.class名 通配选择器:* 组合选择器 交集:ABCDEFG...... 并集:E, F, G, ...... 关系选 ...

  7. python中 with 的作用

    with是 Python2.5 引入的一个新语法,它是一种上下文管理协议,目的在于从流程中吧 try...except 和 finally 关键字和资源释放相关代码统统去掉,简化 try...exce ...

  8. 九 AOP的概述

    AOP : 面向切面编程,解决OOP(面向对象编程)开发遇到的问题,是oop的延伸和扩展 AOP的优点:不修改源码的情况下,对程序进行校验,日志记录,性能控制,事务控制 SpringAOP底层的实现原 ...

  9. CF 1073 E. Segment Sum

    https://codeforces.com/problemset/problem/1073/E 题意:[l,r]中,出现0—9数字的种类数不超过k的数的和 dp[i][j][0/1] 表示 dfs到 ...

  10. CentOS 7 搭建Cobbler实现自动化安装系统

    1.安装软件包 # yum -y install epel-release     #安装EPEL源 # yum -y install cobbler dhcp pykickstart 2.启动cob ...