求一个PHP计算数组内元素的不同组合,请看案例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求一个PHP计算数组内元素的不同组合,请看案例相关的知识,希望对你有一定的参考价值。

比如 我要计算 $arr = array(a,b,c,d,,,,,,,,,);的不同组合 ,并且规定指定所有组合 开始必须是a,结束必须是d, 那么我们得到下面的结果是:
ad abd acd abcd, 这里面的a b c d是指的的任意内容 不限制个数,只是规定第一个值和最后一个值

哪位大神有算法 万分感谢 我实在想不到

除了a和d之外其它元素任意组合的算法有吗,没有的话可以百度一下,本题目需要的就是除了a和d之外其它元素任意组合,输出的时候每一组前面添加a、后面添加d。追问

我举个例子吧 比如我有 abcd四个内容,,那直接要得到的结果是 比如2位数的有 ad
3位数的有 abd acd 4位数的有 abcd acbd

追答

组合有标准算法。只是你要区分组合和排列的概念,组合与顺序无关,下abcd、acbd是一个组合,4个里面取4个形成组合只有一种情况;排列与顺序有关,abcd、acbd是不同的排列,4个里面取4个形成的排列种数有24种(4*3*2*1)。
排列和组合都有标准的算法,非常经典,百度可以查到,各类编程书籍上也有。

参考技术A acbd 算不算合法的

给定数组php中r元素的所有组合

【中文标题】给定数组php中r元素的所有组合【英文标题】:All combinations of r elements from given array php 【发布时间】:2015-01-26 09:18:00 【问题描述】:

给定一个数组,如下所示

$array = ('1', '2', '3', '4', '5', '6', '7');

我正在寻找一种方法来生成所有可能的组合,每个组合所需的元素数量最少。 (例如,如果 r = 5 那么它将返回包含至少 5 个元素的所有可能组合)

【问题讨论】:

我设法用大约 50 行代码完成了它,我得到了 29 个可能的组合。我相信这是正确的答案,考虑到n = 7,它是数组中元素的数量,以及r = 5。所以我们有7C5 + 7C6 + 7C7 = 29。这是你所期待的吗? 这似乎是正确的,你能发布你的代码吗? 【参考方案1】:

kn 项目的组合可以使用以下函数递归定义:

function combinationsOf($k, $xs)
        if ($k === 0)
            return array(array());
        if (count($xs) === 0)
            return array();
        $x = $xs[0];
        $xs1 = array_slice($xs,1,count($xs)-1);
        $res1 = combinationsOf($k-1,$xs1);
        for ($i = 0; $i < count($res1); $i++) 
            array_splice($res1[$i], 0, 0, $x);
        
        $res2 = combinationsOf($k,$xs1);
        return array_merge($res1, $res2);
    

以上是基于递归定义选择k out n元素,可以在列表中固定一个元素x,有C(k-1, xs\x)组合包含x(即@ 987654329@) 和不包含xC(k,xs\xs) 组合(即代码中的res2)。

完整示例:

$array = array('1', '2', '3', '4', '5', '6', '7');

function combinationsOf($k, $xs)
        if ($k === 0)
            return array(array());
        if (count($xs) === 0)
            return array();
        $x = $xs[0];
        $xs1 = array_slice($xs,1,count($xs)-1);
        $res1 = combinationsOf($k-1,$xs1);
        for ($i = 0; $i < count($res1); $i++) 
            array_splice($res1[$i], 0, 0, $x);
        
        $res2 = combinationsOf($k,$xs1);
        return array_merge($res1, $res2);
    

print_r ($array);
print_r(combinationsOf(5,$array));
//print_r(combinationsOf(5,$array)+combinationsOf(6,$array)+combinationsOf(7,$array));

【讨论】:

【参考方案2】:

一个组合可以表示为

nCr = n! / (r! - (n - r)!)

首先,我们将$n 确定为数组中元素的数量。而$r 是每个组合中元素的最小数量。

$a = ['1', '2', '3', '4', '5', '6', '7'];  // the array of elements we are interested in

// Determine the `n` and `r` in nCr = n! / (r! * (n-r)!)
$r = 5;
$n = count($a);

接下来,我们将$max 确定为$n 二进制数字可以表示的最大数。也就是说,如果$n = 3,那么$max = (111)2 = 7。为此,我们首先创建一个空字符串$maxBinary,并在其中添加$n 数量的1s。然后我们将其转换为十进制,并将其存储在$max

$maxBinary = "";
for ($i = 0; $i < $n; $i++)

  $maxBinary .= "1";

$max = bindec($maxBinary);  // convert it into a decimal value, so that we can use it in the following for loop

然后,我们列出从0$max 的每一个二进制数,并存储其中有超过$r1s 的那些。

$allBinary = array();  // the array of binary numbers
for ($i = 0; $i <= $max; $i++)

  if (substr_count(decbin($i), "1") >= $r)  // we count the number of ones to determine if they are >= $r
  
    // we make the length of the binary numbers equal to the number of elements in the array,
    // so that it is easy to select elements from the array, based on which of the digits are 1.
    // we do this by padding zeros to the left.
    $temp = str_pad(decbin($i), $n, "0", STR_PAD_LEFT);
    $allBinary[] = $temp;
  

然后,我们使用与上述相同的技巧为我们的组合选择元素。我相信 cmets 已经足够解释了。

$combs = array();  // the array for all the combinations.
$row = array();    // the array of binary digits in one element of the $allBinary array.

foreach ($allBinary as $key => $one)

  $combs[$key] = "";
  $row = str_split($one);  // we store the digits of the binary number individually
  foreach ($row as $indx => $digit)
  
    if ($digit == '1')  // if the digit is 1, then the corresponding element in the array is part of this combination.
    
      $combs[$key] .= $a[$indx];  // add the array element at the corresponding index to the combination
    
  

就是这样。你完成了!

如果你有类似的东西

echo count($combs);

那么它会给你29

补充说明:

我是在看到您的问题后才阅读的,作为一个新手,我发现这些很有用:

*** - http://en.wikipedia.org/wiki/Combination Php recursion to get all possibilities of strings Algorithm to return all combinations of k elements from n

此外,这里有一些文档的快速链接,应该可以帮助将来看到此内容的人:

http://php.net/manual/en/function.decbin.php http://php.net/manual/en/function.bindec.php http://php.net/manual/en/function.str-pad.php

【讨论】:

你能解释一下你所说的 $r 是每个组合中元素的最小数量吗? 这个想法是用最少的$r 元素生成所有可能的组合。换句话说,我们想要包含$r 或更多元素的组合。希望说明清楚吗?【参考方案3】:
    function arrToBit(Array $element) 
        $bit = '';
        foreach ($element as $e) 
            $bit .= '1';
        
        $length = count($element);
        $num = bindec($bit);
        $back = [];
        while ($num) 
            $back[] = str_pad(decbin($num), $length, '0', STR_PAD_LEFT);
            $num--;
        
        //$back[] = str_pad(decbin(0), $length, '0', STR_PAD_LEFT);
        return $back;
    

    function bitToArr(Array $element, $bit) 
        $num = count($element);
        $back = [];
        for ($i = 0; $i < $num; $i++) 
            if (substr($bit, $i, 1) == '1') 
                $back[] = $element[$i];
            
        
        return $back;
    

    $tags = ['a', 'b', 'c'];
    $bits = arrToBit($tags);
    $combination = [];
    foreach ($bits as $b) 
        $combination[] = bitToArr($tags, $b);
    
    var_dump($combination);

【讨论】:

【参考方案4】:
$arr = array(1,2,3,4,5,6);
$check_value =[];
$all_values = [];
CONT:
$result = $check_value;
shuffle($arr);
$check_value = array_slice($arr,0,3);
if(count($check_value) == 3 && serialize($check_value) !== serialize($result))
$result = $check_value;
array_push($all_values,$result);
goto CONT;


print_r($all_values);

【讨论】:

我们也可以通过GOTO或者递归来实现 Goto is evil.

以上是关于求一个PHP计算数组内元素的不同组合,请看案例的主要内容,如果未能解决你的问题,请参考以下文章

求C语言二维数组元素排列组合?

C语言 怎么计算数组中每一个不同元素出现的次数

php实现全组合算法

php中计算二维数组中某一元素之和的函数是那个啊?谢谢……

怎样求数组中元素重复的次数

ClickHouse 实现数组交并差计算