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的这个子序列倒转

代码实现:

  1. #include<cstdio>
  2. #include<cstring>
  3. void inline swap(char *s1,char *s2){
  4. char t=*s1;
  5. *s1=*s2;
  6. *s2=t;
  7. }
  8. void reverse(char *s,char* e){//反转s到e的子序列
  9. for(e--;s<e;s++,e--)swap(s,e);
  10. }
  11. bool next_permutation(char *start,char *end){
  12. char *cur = end-1, *pre=cur-1;
  13. while(cur>start && *pre>=*cur)cur--,pre--;//找到第一个不满足逆序的位置
  14. if(cur<=start)return false;
  15. for(cur=end-1;*cur<=*pre;cur--);//找到逆序中大于*pre的元素的最小元素
  16. swap(cur,pre);
  17. reverse(pre+1,end);//将尾部的逆序变成正序
  18. return true;
  19. }
  20. int main(){
  21. char s1[]="01224",s2[]="8000";
  22. reverse(s1,s1+strlen(s1));
  23. printf("%s\n",s1);
  24. int n=strlen(s2);
  25. puts("下一个排列:");
  26. int cnt=0;
  27. do{
  28. puts(s2);
  29. cnt++;
  30. }while(next_permutation(s2,s2+n));
  31. printf("%d",cnt);
  32. }

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

题目描述:

设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行中的数是排列总数。

样例输入:

  1. 4
  2. aacc

样例输出:

  1. aacc
  2. acac
  3. acca
  4. caac
  5. caca
  6. ccaa
  7. 6

题解:

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

  1. /**********************************************************
  2. * @Author: Maple
  3. * @Date: 2020-02-22 17:47:36
  4. * @Last Modified by: Maple
  5. * @Last Modified time: 2020-02-22 18:52:34
  6. * @Remark:
  7. **********************************************************/
  8. #include <bits/stdc++.h>
  9. #define lowbit(x) (x&(-x))
  10. #define CSE(x,y) memset(x,y,sizeof(x))
  11. #define INF 0x3f3f3f3f
  12. #define Abs(x) (x>=0?x:(-x))
  13. #define FAST ios::sync_with_stdio(false);cin.tie(0);
  14. using namespace std;
  15. typedef long long ll;
  16. typedef pair<int,int> pii;
  17. typedef pair<ll , ll> pll;
  18. const int maxn=1000;
  19. int n;
  20. char str[maxn];
  21. void swap(char &x,char &y){
  22. char temp=x;
  23. x=y;
  24. y=temp;
  25. return;
  26. }
  27. void reverse(int l){
  28. int i=0;
  29. while(l+i<n-i){
  30. swap(str[l+i],str[n-i]);
  31. i++;
  32. }
  33. return;
  34. }
  35. bool next_permutation(){
  36. int ad=n-1;
  37. //找到第一个不为逆序的元素
  38. for(ad;str[ad]>=str[ad+1];ad--);
  39. if(!(ad>0))
  40. return false;
  41. int ch=n;
  42. //找到第一个
  43. for(ch;str[ch]<=str[ad];ch--);
  44. swap(str[ad],str[ch]);
  45. reverse(ad+1);
  46. return true;
  47. }
  48. int main()
  49. {
  50. #ifndef ONLINE_JUDGE
  51. freopen("in.in","r",stdin);
  52. #endif
  53. cin>>n;
  54. cin>>str+1;
  55. sort(str+1,str+1+n);
  56. int ans=0;
  57. do{
  58. puts(str+1);
  59. ans++;
  60. }while(next_permutation());
  61. cout<<ans<<endl;
  62. return 0;
  63. }

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. 修改oracle数据库用户密码的方法

    WIN+R打开运行窗口,输入cmd进入命令行: 输入sqlplus ,输入用户名,输入口令(如果是超级管理员SYS的话需在口令之后加上as sysdba)进入sql命令行:    连接成功后,输入“s ...

  2. ES2.3.5版本的数据类型

    1,最近使用了2.3.5版本的ES,发现在创建索引的时候出了以下错误. (1)例: POST 192.168.11.166:9200/article3/article/_mapping { " ...

  3. spring boot整合Thymeleaf

    1.引入thymeleaf: <dependency> <groupId>org.springframework.boot</groupId> <artifa ...

  4. Idea 隐藏不必要的文件或文件夹 eg:(.idea,.gitignore,*.iml)

    在使用Idea的时候,有一些文件是不必要的,可以将他们隐藏起来 方法:打开File–>Settings–>Editor如图,在File Types 中的 Ignore files and ...

  5. 攻防世界Web进阶-Upload1

    进入题目 题目提示上传文件,准备好一句话木马. 发现只能上传图片文件,那么再准备一个图片的一句话木马.上传. 浏览器开代理,使用burpsuite拦截,修改文件后缀名为php,否则无法连接 使用蚁剑连 ...

  6. mapreduce程序执行过程

    1.客户端程序,设置作业相关的配置和计算输入分片信息,向RM获取一个JOBID,提交作业信息(分片)到以作业ID为目录下,通知APP——MASTER 2.APP——MASTER,读取指定目录下的作业信 ...

  7. ash.jpg

  8. 38 java 使用标签跳出多层嵌套循环

    public class Interview { public static void main(String[] args) { //使用带标签的break跳出多层嵌套循环 Boolean flag ...

  9. 小程序中data数据的处理方法总结

    wxml代码: <view class="container"> <view wx:for="{{list}}" wx:key="t ...

  10. mysql5.7 忘记root密码修改方式

    参考文档: http://www.jb51.net/article/77858.htm # /etc/init.d/mysql stop --停止mysql服务 # /work/program/mys ...