STL中的全排列实现
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处已经比上一排列的相同位置大了,而为了得到紧邻排列,我们需要将之后的子序列变换至最小排列,由最大排列变换至最小排列,我们只需要倒转这个序列就可。因此总结下来,从一个序列得到他的下一个紧邻排列,需要做:
- 从后向前查找第一个不满足倒序的位置ad
- 从后向前查找第一个大于ad处值的位置ch
- 交换ad和ch处的值
- 将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中的全排列实现的更多相关文章
- STL中关于全排列next_permutation以及prev_permutation的用法
这两个函数都包含在algorithm库中.STL提供了两个用来计算排列组合关系的算法,分别是next_permutation和prev_permutation. 一.函数原型 首先我们来看看这两个函数 ...
- hdu1027 Ignatius and the Princess II (全排列 & STL中的神器)
转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=1027 Ignatiu ...
- STL中的next_permutation
给定一个数组a[N],求下一个数组. 2 1 3 4 2 1 4 3 2 3 1 4 2 3 4 1 ..... 在STL中就有这个函数: 1.参数是(数组的第一个元素,数组的末尾),注意这是前闭后开 ...
- STL中的set容器的一点总结
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- 3.2 STL中的函数对象类模板
*: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...
- C++的模板特化 和 STL中iterator_traits模板的偏特化
C++中有类模板和函数模板,它们的定义如下所示: 类模板: template<class T1,class T2> class C { //... }; 函数模板: template< ...
- C++的STL中vector内存分配方法的简单探索
STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux CentOS 5.2 1.代码 #include <vector> #include <stdio ...
- C++ STL中vector(向量容器)使用简单介绍
原文:http://www.seacha.com/article.php/knowledge/cbase/2013/0903/2205.html C++ vector(向量容器)是一个线性顺序结构.相 ...
- 深入了解STL中set与hash_set,hash表基础
一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(l ...
随机推荐
- Possible overdraw: Root element paints background @drawable/happy with a theme that also paints a background (inferred theme is @style/AppTheme)
安卓界面插入背景图片,当图片内存太大时,界面在切换时会加载失败,这是什么原因呢?这是设置android:background属性时发出的warning: Possible overdraw: Root ...
- Mysql 一些细节方面解析(一)--MyISAM和InnoDB的主要区别和应用场景
myisam和innodb 简介:myisam读的效果好,写的效率差,这和它数据存储格式,索引的指针和锁的策略有关的,它的数据是顺序存储的,他的索引btree上的节点是一个指向数据物理位置的指针,所以 ...
- vue.js ②
1.Vue实例的生命周期钩子 每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听.编译模板.将实例挂载到 DOM 并在数据变化时更新 DOM 等.同时在这个过程中也会运行 ...
- 「JLOI2014」松鼠的新家
「JLOI2014」松鼠的新家 传送门 两种做法: 树上差分 \(O(n)\) 树链剖分 \(O(nlogn)\) 树剖比较好写而且无脑,树上差分复杂度优秀一些但是会有点难调. 这里给出树剖写法: 唯 ...
- php 基础 PHP保留两位小数的几种方法
$num = 10.4567; //第一种:利用round()对浮点数进行四舍五入 echo round($num,2); //10.46 //第二种:利用sprintf格式化字符串 $format_ ...
- @implementer,抽象类,接口
@implementer,抽象类,接口 1. implementer 在看twisted源码时,经常出现@implementer(IReactorFDSet) 它来自zope.interfa ...
- 牛顿迭代法--求任意数的开n次方
牛顿迭代法是求开n次方近似解的一种方法,本文参考. 引言 假如\(x^n = m\),我们需要求x的近似值. 我们设\(f(x) = x^n - m\), 那么也就是求该函数f(x)=0时与x轴的交点 ...
- 4 CSS导航栏&下拉菜单&属性选择器&属性和值选择器
CSS导航栏 熟练使用导航栏,对于任何网站都非常重要 使用CSS你可以转换成好看的导航栏而不是枯燥的HTML菜单 垂直导航栏: <!DOCTYPE html> <html> & ...
- 【剑指Offer面试编程题】题目1362:左旋转字符串--九度OJ
题目描述: 汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S=&qu ...
- [ Pytorch ] torch.squeeze() 和torch.unsqueeze()的用法
squeeze的用法主要就是对数据的维度进行压缩或者解压. squeeze() torch.squeeze(a):去掉a中维数为1的维度. a.squeeze(N):去掉特定维度N下维数为1的维度. ...