必威体育Betway必威体育官网
当前位置:首页 > IT技术

全排列算法

时间:2019-09-28 20:12:12来源:IT技术作者:seo实验室小编阅读:84次「手机版」
 

全排列算法

一、递归法

引用:https://www.cnblogs.com/mengfanrong/p/3854044.html

比如,假设集合是{a,b,c},那么这个集合中元素的全部排列是{(a,b,c),(a,c,b),(b,a,c),(b,c,a),(c,a,b),(c,b,a)},显然,给定n个元素共同拥有n!种不同的排列,假设给定集合是{a,b,c,d},能够用以下给出的简单算法产生其全部排列,即集合(a,b,c,d)的全部排列有以下的排列组成:

(1)以a开头后面跟着(b,c,d)的排列

   (2)以b开头后面跟着(a,c,d)的排列

   (3)以c开头后面跟着(a,b,d)的排列

   (4)以d开头后面跟着(a,b,c)的排列,这显然是一种递归的思路,于是我们得到了下面的实现:

#include<iOStream>
#include<string>
using namespace std;

re_comb(string a,int k,int len)//k表示当前递归第一个数的位置 
{
	int i;
	if(k==len)//当k=len时,输出;即,每一位都已经确定。 
	{         //然后退出一层,接着for循环,再输出 
		cout<<a<<endl;
	} 
	else
	{
		for(i=k;i<len;i++)
		{
			swap(a[i],a[k]);
			re_comb(a,k+1,len);//将k位置之后的元素进行全排列。 
			swap(a[i],a[k]);//恢复 
		}
	}
} 

int main()
{
	string a;
	getline(cin,a);
	re_comb(a,0,a.length());
	return 0;
} 

先定下第i位,然后将第i位之后的数全排列。

二、字典序法

引用:https://blog.csdn.net/cpfeed/article/details/7376132

算法定义

首先看什么叫字典序,顾名思义就是按照字典的顺序(a-z, 1-9)。以字典序为基础,我们可以得出任意两个数字串的大小。比如 "1" < "12"<"13"。 就是按每个数字位逐个比较的结果。对于一个数字串,“123456789”, 可以知道最小的串是 从小到大的有序串“123456789”,而最大的串是从大到小的有序串“*987654321”。这样对于“123456789”的所有排列,将他们排序,即可以得到按照字典序排序的所有排列的有序集合。

如此,当我们知道当前的排列时,要获取下一个排列时,就可以范围有序集合中的下一个数(恰好比他大的)。比如,当前的排列时“123456879”, 那么恰好比他大的下一个排列就是“123456897”。 当当前的排列时最大的时候,说明所有的排列都找完了。

于是可以有下面计算下一个排列的算法:

设P是1~n的一个全排列:p=p1p2......pn=p1p2......pj-1pjpj+1......pk-1pkpk+1......pn

1)从排列的右端开始,找出第一个比右边数字小的数字的序号j(j从左端开始计算),即 j=max{i|pi<pi+1}  

2)在pj的右边的数字中,找出所有比pj大的数中最小的数字pk,即 k=max{i|pi>pj}(右边的数从右至左是递增的,因此k是所有大于pj的数字中序号最大者)  

3)对换pi,pk   

4)再将pj+1......pk-1pkpk+1......pn倒转得到排列p'=p1p2.....pj-1pjpn.....pk+1pkpk-1.....pj+1,这就是排列p的下一个排列。

上面解释的相当清楚,这里稍微提一些点

1、为什么要从右向左查找?  因为这样能确保变化最小,即找到的数仅比现在的数大一丢丢。

2、为什么是找到第一个比右边小的数?因为这确保说明还有更大的数。

3、为什么要再从右向左找,找第一个比其大的数?  因为从左到右是逐渐增加,第一个比起大,互换后,增加最少(一丢丢)

4、上面引用的第四步,为什么要倒转,互换?   因为从左到右是逐渐增加,要只增加一丢丢。

上面在c++的stl库函数中,为next_permutation(按字典序,找排列组合的下一个元素)

如果觉得懂了,理解透了。可以尝试思考一下,prev_permutation(按字典序,找排列组合的上一个元素)

#include<iostream>
#include<algorithm> 
#include<string>
using namespace std;

int main()
{
	string s;
	getline(cin,s); 
	sort(s.begin(),s.end());
	do
	{
		cout<<s<<endl;
	}while(next_permutation(s.begin(),s.end()));
	return 0;
}

除了上面的排列方法,常见的排列算法有:递增进位制数法、递减进位制数法、邻位对换法

相关阅读

除夕错发万元红包:3个多小时大部分群友将钱全部退还

A5创业网(公众号:iadmin5)2月13日报道,过年期间,为了活跃群里气氛,很多群友选择发红包的方式来让大家乐呵乐呵。不过发红包时,如果发错金

悉见科技第二代AR智能眼镜XMAN全面测评

2019年1月15日,悉见科技AR&AI眼镜XMAN获得了虚拟与增强现实产业金V奖「最佳硬件」奖。此外,悉见科技创始人兼CEO刘洋还受邀参加北大

防火常识大全

林火爆燃等极端情况往往发生突然,难以防范,但我们在日常生活中可以通过掌握一些防火防灾知识,避免火灾的发生和生命的消逝。 原文地

别装了,算法知道你值多少钱

好吧,一个标题党的标题,但是本质上也没有任何夸大,算法的确知道你值多少钱,并决定向你展示什么样的广告。自从Facebook引入oCPM出价以

自定义RadioGroup实现多行排列

今天做一个单选框,效果如下:这里需要自定义一个RadioGrouppackage yisu.cn.wedgit; import android.content.Context; import andr

分享到:

栏目导航

推荐阅读

热门阅读