滚雪球思路 计算一个字符串所有可能的排列顺序
2012-05-27 00:10
375 查看
今天一同学丢了个问题给我,怎么列出一个字符串所有的排列可能性
刚开始的思路是,先取第一位不同,比如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循环来完成,
如果只加了一个c,那么这样每次计算出来的结果就是我们想要的结果了
现在给定的字符串是未知的,所以要考虑到一直添加新的字符串到最小的组合中
我想到了用递归来完成这个操作,码出代码如下:
写完之后发现用递归有些浪费了,完全没有必要。。。对上面的代码做了下优化,最终结果如下:
刚开始的思路是,先取第一位不同,比如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循环来完成,
$str = 'ab'; $newstr = 'c'.$str; $len = strlen($str); //考虑到后面还要经常使用现在算出来的结果,所以用了一个数组来放置结果 $arr = array(); for($i=0;$i<$len;$i++){ $arr[] = strtr($newstr,array($newstr[0]=>$newstr[$i],$newstr[$i]=>$newstr[0])); }
如果只加了一个c,那么这样每次计算出来的结果就是我们想要的结果了
现在给定的字符串是未知的,所以要考虑到一直添加新的字符串到最小的组合中
我想到了用递归来完成这个操作,码出代码如下:
$str = 'abcd'; $len = strlen($str); $arr = array($str[$len-1]); $return = ''; getStr($str,$arr,$len-2,$return); print_r($return); function getStr($str,$arr,$n,&$return){ if($n>=0){ $newarr = array(); foreach($arr as $v){ $temp = $str[$n].$v; $l = strlen($temp); for($i=0;$i<$l;$i++){ $newarr[] = strtr($temp,array($temp[0]=>$temp[$i],$temp[$i]=>$temp[0])); } } getStr($str,$newarr,$n-1,$return); } else { $return = $arr; } }
写完之后发现用递归有些浪费了,完全没有必要。。。对上面的代码做了下优化,最终结果如下:
$str = 'abc'; $return = getStr($str); print_r($return); function getStr($str){ $len = strlen($str); $arr = array($str[0]); for($i=1;$i<$len;$i++){ $newarr = array(); foreach($arr as $v){ $temp = $str[$i].$v; $l = strlen($temp); for($j=0;$j<$l;$j++){ $newarr[] = strtr($temp,array($temp[0]=>$temp[$j],$temp[$j]=>$temp[0])); } } $arr = $newarr; } return $arr; }
相关文章推荐
- 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。 结果请按字母顺序输出。
- 给定一个字符串,输出其所有的可能排列
- 手把手地写了一个函数,计算出两个字符串日期之间的所有字符串型日期 集合
- 对于给定的字符串,求其入栈后,所有可能的出栈顺序
- java 输入一个字符串,打印出该字符串中字符的所有排列
- 不同的取法输出顺序可以不考虑。取字符( 从标准输入读入一个由字母构成的串(不大于30个字符)。从该串中取出3个不重复的字符,求所有的取法。取出的字符,要求按字母升序排列成一个串。)
- 笔试题:给出一个函数来输出字符串的所有排列
- 手把手地写了一个函数,计算出两个字符串日期之间的所有字符串型日期 集合
- 编写一个在1,2,…,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。例如:1 + 2 + 34 – 5 + 67 – 8 + 9 = 100。
- 编写一个方法,返回某字符串的所有排列组合。
- 给定一个只包含小写字母的字符串,删除重复的字母,每个字母只出现一次。在所有结果中,输出字典顺序最小的。
- java 输入一个字符串,打印出该字符串中字符的所有排列
- 按字典顺序打印字符串的所有排列
- 输入一个字符串,打印出该字符串中字符的所有排列
- 字符串所有可能的排列 例如abcd等等 递归算法和排列组合知识结合
- 给出一个函数来输出一个字符串的所有排列
- 每天一道LeetCode-----将字符串切分,使每个子串都是回文串,计算所有可能结果和最小切分次数
- 输入一个字符串,打印出该字符串中字符的所有排列
- 给出一个函数来输出一个字符串的所有排列
- 3、给出一个函数输出字符串的所有排列