滚雪球思路 计算一个字符串所有可能的排列顺序

今天一同学丢了个问题给我,怎么列出一个字符串所有的排列可能性

刚开始的思路是,先取第一位不同,比如abcd

那取第一位不同的话就有四种可能abcd、bacd、cbad、dcba

这样就想到了用for去循环4次,然后再对后面的组合进行排列

比如abcd,分别取后面三个字母,每个字母出现的位置有三种可能

如:b的话,三个位置为abcd、acbd、acdb

因为结果有重复数据,所以用上了array_unique排重,

后来才发现漏了点什么,因为每次算出来的结果排重后数量都不对

仔细研这分一下发现问题所在

比如abcd中b在第一个位置时,我只算了abcd,漏掉了一种可能就是abdc

至此,前面的想法全部抛弃了。。。

从错误中发现一个问题,就是每两个字母都有可能调整换位置

换言之,要排列所有的可能,就要从最小的组合开始

那么就从两个字母开始排列,假设a和b

可能的顺序为ab 和ba

这时候如果再多一个字母c

那么可能出现的排列变为 cab  acb  abc和 cba bca bac

从上面能看出来,从最小的组合开始,每当加入一个新的字母时的规律为

用新加的字母对原来的组合中的每一个成员,如上面的ab和ba,分别插入

插入后再将新插入的字母所有可能插入的位置进行计算,

如上面的ab插入c后,c可能出现在左中右

这里可以用一个for循环来完成,

1 $str = 'ab';
2 $newstr = 'c'.$str;
3 $len = strlen($str);
4 //考虑到后面还要经常使用现在算出来的结果,所以用了一个数组来放置结果
5 $arr = array();
6 for($i=0;$i<$len;$i++){
7   $arr[] = strtr($newstr,array($newstr[0]=>$newstr[$i],$newstr[$i]=>$newstr[0]));
8 
9 }

如果只加了一个c,那么这样每次计算出来的结果就是我们想要的结果了

现在给定的字符串是未知的,所以要考虑到一直添加新的字符串到最小的组合中

我想到了用递归来完成这个操作,码出代码如下:

 1 $str = 'abcd';
 2 $len = strlen($str);
 3 $arr = array($str[$len-1]);
 4 $return = '';
 5 getStr($str,$arr,$len-2,$return);
 6 print_r($return);
 7 
 8 function getStr($str,$arr,$n,&$return){
 9     if($n>=0){
10         $newarr = array();
11         foreach($arr as $v){
12             $temp = $str[$n].$v;
13             $l = strlen($temp);
14             for($i=0;$i<$l;$i++){
15                 $newarr[] = strtr($temp,array($temp[0]=>$temp[$i],$temp[$i]=>$temp[0]));
16             }
17         }
18         getStr($str,$newarr,$n-1,$return);
19     } else {
20         $return = $arr;
21     }
22 }

 写完之后发现用递归有些浪费了,完全没有必要。。。对上面的代码做了下优化,最终结果如下:

 1 $str = 'abc';
 2 $return = getStr($str);
 3 print_r($return);
 4 function getStr($str){
 5     $len = strlen($str);
 6     $arr = array($str[0]);
 7     for($i=1;$i<$len;$i++){
 8         $newarr = array();
 9         foreach($arr as $v){
10             $temp = $str[$i].$v;
11             $l = strlen($temp);
12             for($j=0;$j<$l;$j++){
13                 $newarr[] = strtr($temp,array($temp[0]=>$temp[$j],$temp[$j]=>$temp[0]));
14             }
15         }
16         $arr = $newarr;
17     }
18     return $arr;
19 }

posted on 2012-05-27 00:10  cnbeir  阅读(827)  评论(1编辑  收藏  举报

导航