PHP_字典序法获得排列组合

前段时间一次聚会闲聊时聊到一个问题,就是给你一排数组,例如1,2,3,4,5,如何能高效的获取上述数列的所有排列组合,正巧没事,研究了一下,一开始以为是个很简单的问题,就直接开始写代码了,后来发现怎么循环也不理想,基本上都有一些不必要的消耗,百度一下看到一个不错的算法,字典序法,顺便学习一下,然后记录之。

摘一段算法思想:

设P是[1,n]的一个全排列。

P=P1P2…Pn=P1P2…Pj-1PjPj+1…Pk-1PkPk+1…Pn , j=max{i|Pi<Pi+1}, k=max{i|Pi>Pj} ,对换Pj,Pk,将Pj+1…Pk-1PjPk+1…Pn翻转, P’= P1P2…Pj-1PkPn…Pk+1PjPk-1…Pj+1即P的下一个

例子:839647521的下一个排列.

从最右开始,找到第一个比右边小的数字4(因为4<7,而7>5>2>1),再从最右开始,找到4右边比4大的数字5(因为4>2>1而4<5),交换4、5,此时5右边为7421,倒置为1247,即得下一个排列:839651247.用此方法写出全排列的非递归算

感觉还是挺明了的,在纸上稍微写了一下,然后稍作验证,确实不错,然后自己用PHP实现了一下:


/*

 
字典序法获取所有排列

 
@最后更新时间:03/05/2014

 
@作者:toryzen(toryzen.com)

 
@备注,备注中示例用ABC顺序表示

*/

function
getPars(
$arr
){

    
//正向排列

    
sort(
$arr
);

    
//获取数组长度

    
$len
=
count
(
$arr
)-1;

    
//记录传入的排列

    
$return
[] =
$arr
;

    
while
(TRUE){

        
//从右侧开始找到第一个左侧(A)<右侧(B)的数字序列

        
for
(
$i
=
$len
;
$i
>=0;
$i
--){

            
if
(
$arr
[
$i
]>
$arr
[
$i
-1]){

                
$here
=
$i
-1;

                
break
;

            
}

        
}

        
//若找到了则开始换位

        
if
(
$here
>=0){

            
//从有右向左侧找,第一个比左侧(A)大的数字(C)交换位置得到CBA

            
for
(
$j
=
$len
;
$j
>
$here
;
$j
--){

                
if
(
$arr
[
$here
]<
$arr
[
$j
]){

                    
$revers
=
$j
;

                    
list(
$arr
[
$here
],
$arr
[
$j
]) =
array
(
$arr
[
$j
],
$arr
[
$here
]);

                    
break
;

                
}

            
}

            
//将后续数字倒序得到CAB

            
unset(
$newarr
);

            
for
(
$h
=
$here
+1;
$h
<=
$len
;
$h
++){

                
$newarr
[] =
$arr
[
$h
];

                
unset(
$arr
[
$h
]);

            
}

            
$return
[] =
$arr
=
array_merge
(
$arr
,
array_reverse
(
$newarr
,TRUE));

        
}
else
{

            
break
;

        
}

    
}

    
return
$return
;

}

$arr
=
array
(1,4,3,2);

print_r(getPars(
$arr
));

除了这个还有一个递归法,But自己的递归学的不是很好,而且所有的递归都能用循环解决随用循环,改天有时间,再研究一下递归,老是转不过弯来。

时间: 2024-08-22 07:45:26

PHP_字典序法获得排列组合的相关文章

插板法(排列组合)

插板法的条件 (1)每个元素都是相同的 (2)分成的组,每组的元素不为空 就比如下面这个例子,分出来的组的元素是不为空的 将10个相同的球放到3个不同的篮子里面去,每个篮子至少一个,问有多少种放法 0-0-0-0-0-0-0-0-0-0     0代表球,-代表板子, 将9个板插入到10个球中, 我们只要从中选出2个板子, 自然而然就把球分成三堆了 即C(9,2) 将10个相同的球放到3个不同的篮子里面去,每个篮子可以为空,问有多少种方法 因为每个篮子可以为空,即每组的元素可以为空, 不符合第二

排列组合常见解题方法

由 27 October in ss 中的一道题阐发: 拓展:把 \(n\) 个相同物品放入 \(m\) 个篮子, 若 (1) 篮子可以为空, 篮子不同:共有 \(C_{n+m-1}^{m-1}\) 种方案. (2) 篮子不可以为空, 篮子不同:共有 \(C_{n-1}^{m-1}\) 种方案. (挡板法) (3) 篮子可以为空, 篮子相同:方案递推式为 \(f(n,m)=f(n-1,m)+f(n,m-1)\). (4) 篮子不可以为空, 篮子相同:方案算式为 \(f'(n,m)=f(n-m,m

[LeetCode] Permutations 排列生成算法之字典序法

字典序排序生成算法 字典序法就是按照字典排序的思想逐一产生所有排列. 例如,由1,2,3,4组成的所有排列,从小到大的依次为: 1234, 1243, 1324, 1342, 1423, 1432, 2134, 2143, 2314, 2341, 2413, 2431, 3124, 3142, 3214, 3241, 3412, 3421, 4123, 4132, 4213, 4231, 4312, 4321. 分析这种过程,看后一个排列与前一个排列之间有什么关系? 再如,设有排列(p)=276

JavaScript 递归法排列组合二维数组2

<html> <head> <title>二维数组排列组合</title> </head> <body> <div id="showDiv"></div> </body> <script type="text/javascript"> var arrays = [ [ '1-1-雨尘', '1-2-芸芸', '1-3-简一', '1-4-乐乐' ]

JavaScript 递归法排列组合二维数组

<html> <head> <title>二维数组排列组合</title> </head> <body> <div id="showDiv"></div> </body> <script type="text/javascript"> var arrays = [ [ '1-1-雨尘', '1-2-芸芸', '1-3-简一', '1-4-乐乐' ]

【程序员眼中的统计学(5)】排列组合:排序、排位、排

排列组合:排序.排位.排 作者 白宁超 2015年10月15日18:30:07 摘要:程序员眼中的统计学系列是作者和团队共同学习笔记的整理.首先提到统计学,很多人认为是经济学或者数学的专利,与计算机并没有交集.诚然在传统学科中,其在以上学科发挥作用很大.然而随着科学技术的发展和机器智能的普及,统计学在机器智能中的作用越来越重要.本系列统计学的学习基于<深入浅出统计学>一书(偏向代码实现,需要读者有一定基础,可以参见后面PPT学习).正如(吴军)先生在<数学之美>一书中阐述的,基于统

排列组合

(常考)错位排列 有N封信和N个信封,每封信都不装在自己信封里的排列种数记作Dn,则 D1=0,D2=1,D3=2,D4=9,D5=44,D6=265 一.相邻问题---捆绑法 不邻问题---插空法 对于某几个元素不相邻的排列问题,可先将其他元素排好,再将不相邻元素在已排好的元素之间及两端空隙中插入即可. [例题1]一张节目表上原有3个节目,如果保持这3个节目的相对顺序不变,再添进去2个新节目,有多少种安排方法? A.20 B.12 C.6 D.4 [答案]A. [解析] 以下内容需要回复才能看

【noi 2.6_9288】&amp;【hdu 1133】Buy the Ticket(DP / 排列组合 Catalan+高精度)

题意:有m个人有一张50元的纸币,n个人有一张100元的纸币.他们要在一个原始存金为0元的售票处买一张50元的票,问一共有几种方案数. 解法:(学习了他人的推导后~) 1.Catalan数的应用7的变形.(推荐阅读:http://www.cnblogs.com/chenhuan001/p/5157133.html).P.S.不知我之前自己推出的公式“C(n,m)*C(2*m,m)/(m+1)*P(n,n)*P(m,m)”是否是正确的. (1)在不考虑m人和n人本身组内的排列时,总方案数为C(m+

排列组合知识

1.在不全相异的n个物体中,其中有n1个物体是相同的,n2个物体是相同的,……nk个物体是相同的.全部物体的种类数为k,则这n个物体的全排列数为 n!/(n1!*n2!*……*nk!) 2.用n-1条边将n个顶点连接的图有n^(n-2)个. 3.圆周排列 从N个元素中取出R个元素形成圆周排列,排列数为A(N,R)/R; 同理,N个元素的圆周排列数为(N-1)!; 4.按字典序生成下一个排列组合 ①从后往前找第一个正序的尾下标i,pi>p(i-1),pi>p(i+1): ②找p(i-1)后面其大