// 下午一同事提出一个有趣的问题:一行字母(数字符号也行),中间插入特定字符(字符类型不定,我这里用加号),字母的顺序不能变,如下:
ab => a+b 1种
abc=>a+bc;ab+c;a+b+c 3种
abcd=>a+bcd;ab+cd;a+b+cd;abc+d;a+bc+d;ab+c+d;a+b+c+d 7种
一次类推。
搞了差不多一下午,终于搞出来了;说说我的思路:先将字符串(一行字母)分割成数组,再对数组进行随机组合排列(组合排列中用+连接);形成“可以排列的多少种数组”;对新数组循环,循环中将每个元素的+替换成"" 将替换后的元素与ABCD比较不一样的就删除;代码如下:
public function countnum(){
$chars = 'abcd'; // ab / abc / abcd / abcde 随便设
$str_array = str_split($chars); // 对abcd拆分 0=>a, 1=>b, 2=>c,3=>d
$res = array();
$spe_array = $this->arrangement($str_array);
foreach($spe_array as $v) {
$res = array_merge($res, $this->foo(explode(' ', trim($v))));
}
foreach ($res as $key=>$val){
$vals = str_replace("+","",$val);
if($vals != $chars){ // 主要是这里思路最敏捷,合并后与原来的字符画比较,而不用一步一步的做判断
unset($res[$key]);
}
}
unset($res['0']);
echo '<pre>';
print_r($res);
}
// 下面2个函数是随机排列的最大种类,无需改动***************start*********************
function arrangement($arr = array(), $res = '') {
if(! is_array($arr) ) $arr = str_split($arr);
if(empty($arr)) $array[] = $res;
else
foreach($arr AS $k => $v) {
unset($arr[$k]);
foreach( $this->arrangement($arr, $res . " $v") AS $t) $array[] = $t;
$arr[$k] = $v;
}
return $array;
}
function foo($ar) {
$res = array();
if(count($ar) > 2) {
$t = array_shift($ar);
foreach($this->foo($ar) as $v) {
$res[] = "$t$v";
$res[] = "$t+$v";
}
}else {
$res[] = "$ar[0]$ar[1]";
$res[] = "$ar[0]+$ar[1]";
}
return $res;
}
//***************end*********************
效果:
ab
Array ( [1] => a+b )
abc
Array ( [1] => a+bc [2] => ab+c [3] => a+b+c )
abcd
Array ( [1] => a+bcd [2] => ab+cd [3] => a+b+cd [4] => abc+d [5] => a+bc+d [6] => ab+c+d [7] => a+b+c+d )
abcde
Array ( [1] => a+bcde [2] => ab+cde [3] => a+b+cde [4] => abc+de [5] => a+bc+de [6] => ab+c+de [7] => a+b+c+de [8] => abcd+e [9] => a+bcd+e [10] => ab+cd+e [11] => a+b+cd+e [12] => abc+d+e [13] => a+bc+d+e [14] => ab+c+d+e [15] => a+b+c+d+e )
// 这也许不是最简便的方法,欢迎各位指导高效简洁的方法,在此感谢啦!!