PHP实现全排列(递归算法)

算法描述:如果用P表示n个元素的全排列,而Pi表示n个元素中不包含元素i的全排列,(i)Pi表示在排列Pi前面加上前缀i的排列,那么n个元素的全排列可递归定义为:
    ① 如果n=1,则排列P只有一个元素i;
    ② 如果n>1,则全排列P由排列(i)Pi构成;
根据定义,可以看出如果已经生成(k-1)个元素的排列Pi,那么k个元素的排列可以在每个Pi前面加上元素i而生成。

1、

 1 <?php
 2 function rank($base, $temp=null)
 3 {
 4     $len = strlen($base);
 5     if($len <= 1)
 6     {
 7         echo $temp.$base.‘<br/>‘;
 8     }
 9     else
10     {
11         for($i=0; $i< $len; ++$i)
12         {
13             rank(substr($base, 0, $i).substr($base, $i+1, $len-$i-1), $temp.$base[$i]);
14         }
15     }
16 }
17 rank(‘123‘);

不过,这样的算法有个问题:若是存在相同的元素,则全排列有重复。例如‘122‘的全排列只有三种情况:‘122‘、‘212‘、‘221‘;上面方法却有重复。

2、在上面算法的基础上价格判重操作即可

 1 <?php
 2 function fsRank($base, $temp=null)
 3 {
 4     static $ret = array();
 5     $len = strlen($base);
 6     if($len <= 1)
 7     {
 8         //echo $temp.$base.‘<br/>‘;
 9         $ret[] = $temp.$base;
10     }
11     else
12     {
13         for($i=0; $i< $len; ++$i)
14         {
15             $had_flag = false;
16             for($j=0; $j<$i; ++$j)
17             {
18                 if($base[$i] == $base[$j])
19                 {
20                     $had_flag = true;
21                     break;
22                 }
23             }
24             if($had_flag)
25             {
26                 continue;
27             }
28             fsRank(substr($base, 0, $i).substr($base, $i+1, $len-$i-1), $temp.$base[$i]);
29         }
30     }
31     return $ret;
32 }
33 print ‘<pre>‘;
34 print_r(fsRank(‘122‘));
35 print ‘</pre>‘;
36 ?>
时间: 2024-08-25 21:11:26

PHP实现全排列(递归算法)的相关文章

字符串的全排列-递归算法

题目:给定字符串S[0...N-1],设计算法,枚举S的全排列. 假设字符串为“1234”,首先考虑1,然后问题就变成了考虑“234”的全排列,所以问题规模缩小了1,然后再考虑2,依次类推.可以采用递归算法. 1-234 2-134 3-124 4-123 假设有重复字符,则重复字符的全排列就是每个字符分别与它后面非重复出现的字符交换. 1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 //

C++输出全排列递归算法详细解释

中心思想: 设R={r1,r2,-,rn}是要进行排列的n个元素,Ri=R-{ri}. Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列. (1)当n=1时,Perm(R)=(r),其中r是集合R中唯一的元素: (2)当n>1时,Perm(R)可由(r1)+Perm(R1),(r2)+Perm(R2),-,(rn)+Perm(Rn)构成. 那么具体程序要怎么实现呢?我们来个实际的例子,假设有一数列1,2,3,4 那么1,2,3,4的全排列 perm({1,2,3,4}

全排列递归算法

固定第一个字符,递归取得首位后面的各种字符串组合:      * 再把第一个字符与后面每一个字符交换,并同样递归获得首位后面的字符串组合: *递归的出口,就是只剩一个字符的时候,递归的循环过程,就是从每个子串的第二个字符开始依次与第一个字符交换,然后继续处理子串.      *      * 假如有重复值呢?      * *由于全排列就是从第一个数字起,每个数分别与它后面的数字交换,我们先尝试加个这样的判断--如果一个数与后面的数字相同那么这两个数就不交换了.      * 例如abb,第一个

递归解决全排列生成算法

排列:从n个元素中任取m个元素,并按照一定的顺序进行排列,称为排列: 全排列:当n==m时,称为全排列: 比如:集合{ 1,2,3}的全排列为: { 1 2 3} { 1 3 2 } { 2 1 3 } { 2 3 1 } { 3 2 1 } { 3 1 2 } 方法一: 我们可以将这个排列问题画成图形表示,即排列枚举树,比如下图为{1,2,3}的排列枚举树,此树和我们这里介绍的算法完全一致: 算法思路: (1)n个元素的全排列=(n-1个元素的全排列)+(另一个元素作为前缀): (2)出口:如

全排列问题的递归算法(Perm)

[题目]设计一个递归算法生成n个元素{r1,r2,-,rn}的全排列. [算法讲解] 设R={r1,r2,-,rn}是要进行排列的n个元素,Ri=R-{ri}.集合X中元素的全排列记为perm(X).(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列.R的全排列可归纳定义如下: 当n=1时,perm(R)=(r),其中r是集合R中唯一的元素:当n>1时,perm(R)由(r1)perm(R1),(r2)perm(R2),-,(rn)perm(Rn)构成.实现思想:将

算法学习(二) 全排列问题的非递归算法——模拟堆栈

前一段时间总结了全排列问题的几种递归解法,今天再总结一下如何通过对系统栈行为的模拟来非递归的实现全排列问题. 我们用一个数组stack[]来表示一个栈,用一个top指针来表示栈顶,用一个flags[]数组来标示每一个数字的可用性:用i来表示当前的状态. 初始状态top=0:i=-1:flags数组全为1: i递增,如果i没有越界并且flags[i]==1,那么就将i写入栈中,栈顶往前移动一位:最后把flags[i]赋值为0,i回溯到初始状态-1: 当栈顶越界,就将整个栈的信息打印出来,然后top

字符串全排列-非递归算法

字符串的全排列非递归算法是每次都寻找比前序列大一点的序列,如: 起点:字典序最小的排列,例如12345 终点:字典序最大的排列,例如54321 过程:从当前排列生成字典序刚好比它大的下一个排列. 算法过程:后找.小大.交换.翻转 后找:字符串中最后一个升序的位置i,即S[k]>S[k+1](k>i),S[i]<S[i+1]: 查找(小大):S[i+1...N-1]中比Ai大的最小值Sj: 交换:Si,Sj: 翻转:S[i+1...N-1] 代码如下: 1 #include <ios

全排列的非递归算法

1.全排列的定义和公式: 从n个数中选取m(m<=n)个数按照一定的顺序进行排成一个列,叫作从n个元素中取m个元素的一个排列.由排列的定义,显然不同的顺序是一个不同的排列.从n个元素中取m个元素的所有排列的个数,称为排列数.从n个元素取出n个元素的一个排列,称为一个全排列.全排列的排列数公式为n!,通过乘法原理可以得到. 2.时间复杂度: n个数(字符.对象)的全排列一共有n!种,所以全排列算法至少时间O(n!)的.如果要对全排列进行输出,那么输出的时间要O(n?n!),因为每一个排列都有n个数

递归算法:求序列的全排列

用C++模板书写一段序列数组的全部排列 /** * 书本:[windows程序设计] * 功能:输出全部的排列情况 * 文件:全排列.cpp * 时间:2014年9月29日21:52:55 * 作者:cutter_point */ #include <iostream> using namespace std; //交换两个元素的函数 template<class Type> inline void Swap(Type &a, Type &b) //取两个元素的引用