【问题标题】:All combinations of r elements from given array php给定数组php中r元素的所有组合
【发布时间】: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。这是你所期待的吗?
  • 这似乎是正确的,你能发布你的代码吗?

标签: php arrays combinations


【解决方案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

    补充说明:

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

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

    【讨论】:

    • 你能解释一下你所说的 $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或者递归来实现
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-17
      • 2013-07-30
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      • 2022-01-25
      • 2023-04-10
      相关资源
      最近更新 更多