数学上的排列组合

// 下午一同事提出一个有趣的问题:一行字母(数字符号也行),中间插入特定字符(字符类型不定,我这里用加号),字母的顺序不能变,如下:

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
)

// 这也许不是最简便的方法,欢迎各位指导高效简洁的方法,在此感谢啦!!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值