从给定数量的元素的数组中获取所有唯一组合

时间:2014-10-22 08:58:40

标签: php algorithm recursion combinations subset-sum

我希望有一种方法可以获得给定数组长度的所有给定数字的所有组合。 在我的项目中,数组大小通常为7.所以我写了一个这样的测试代码,看看我是否可以得到所有需要的组合。重要的是每个结果数组必须是唯一的,最大数组大小必须是7。

<?php
$numbers = [1, 2, 3, 4, 5, 6, 7];

$arraysize = 7;

$subset = [];
$count = count($numbers);
for ($i = 0; $i < $count; $i++) {
    $subset[] = $numbers[$i];
}

for ($i=0; $i < $count; $i++) {
    for ($j=$i; $j < $count; $j++) {
        $subset[] = $numbers[$i] . $numbers[$j];
    }
}

for ($i=0; $i < $count; $i++) {
    for ($j=$i; $j < $count; $j++) {
        for ($k=$j; $k < $count; $k++) {
            $subset[] = $numbers[$i] . $numbers[$j] . $numbers[$k];
        }
    }
}

for ($i=0; $i < $count; $i++) {
    for ($j=$i; $j < $count; $j++) {
        for ($k=$j; $k < $count; $k++) {
            for ($l=$k; $l < $count; $l++) {
                $subset[] = $numbers[$i] . $numbers[$j] . $numbers[$k] . $numbers[$l];
            }
        }
    }
}

for ($i=0; $i < $count; $i++) {
    for ($j=$i; $j < $count; $j++) {
        for ($k=$j; $k < $count; $k++) {
            for ($l=$k; $l < $count; $l++) {
                for ($m=$l; $m < $count; $m++) {
                    $subset[] = $numbers[$i] . $numbers[$j] . $numbers[$k] . $numbers[$l] . $numbers[$m];
                }
            }
        }
    }
}

for ($i=0; $i < $count; $i++) {
    for ($j=$i; $j < $count; $j++) {
        for ($k=$j; $k < $count; $k++) {
            for ($l=$k; $l < $count; $l++) {
                for ($m=$l; $m < $count; $m++) {
                    for ($n=$m; $n < $count; $n++) {
                        $subset[] = $numbers[$i] . $numbers[$j] . $numbers[$k] . $numbers[$l] . $numbers[$m] . $numbers[$n];
                    }
                }
            }
        }
    }
}

for ($i=0; $i < $count; $i++) {
    for ($j=$i; $j < $count; $j++) {
        for ($k=$j; $k < $count; $k++) {
            for ($l=$k; $l < $count; $l++) {
                for ($m=$l; $m < $count; $m++) {
                    for ($n=$m; $n < $count; $n++) {
                        for ($o=$n; $o < $count; $o++) {
                            $subset[] = $numbers[$i] . $numbers[$j] . $numbers[$k] . $numbers[$l] . $numbers[$m] . $numbers[$n] . $numbers[$o];
                        }
                    }
                }
            }
        }
    }
}

echo "<pre>";
print_r($subset);
echo "</pre>";
?>

当我运行这段代码时,我得到了我想要的组合(我将组合作为字符串来清楚地看到结果,但通常$subset数组中的每个结果项都必须是数组) 使用此代码,我可以获得所有独特的组合。

但是你可以看到这段代码很难看。我试图让它成为一个递归函数,但我失败了。有人能指出我正确的方向来获得完全相同的结果吗? ($subset数组中的每个项通常必须是包含数字的数组)

4 个答案:

答案 0 :(得分:0)

您可以使用以下方法简化此逻辑(并使代码不那么难看),而无需递归:

for ($i = 0; $i < $count; $i++) {
    $subset[] = $numbers[$i];
    for ($j=$i; $j < $count; $j++) {
        $subset[] = $numbers[$i] . $numbers[$j];
        for ($k=$j; $k < $count; $k++) {
            $subset[] = $numbers[$i] . $numbers[$j] . $numbers[$k];
            for ($l=$k; $l < $count; $l++) {
                $subset[] = $numbers[$i] . $numbers[$j] . $numbers[$k] . $numbers[$l];
            }
        }
    }
}

答案 1 :(得分:0)

即使您的数组中有重复的数字

,以下内容也适用于所有情况
$array = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14);  
 sort($array);  //in case it 's not sorted
 $array = array_slice($array,-7);   
 $num = count($array );  
  $total = pow(2, $num);
  $result= array();
  $element='';
   for ($i = 0; $i < $total; $i++) 
    {      

          for ($j = 0; $j < $num; $j++) 
              {                 
                 if (pow(2, $j) & $i) 
                 {
                 $element=$element.$array [$j];                 
                 }                                       
              }
              $result[]=$element;
              $element=''; 
      }
      print_r($result);

答案 2 :(得分:0)

此实现返回所有项目的所有组合(7 7 = 823542 7项组合):

function combine_all(array $numbers) {
    $count = count($numbers);

    $result = array_map('strval', $numbers);
    for($i = 1; $i < $count; ++$i) {
        $combinations = array_slice($result, pow($count, $i-1));
        foreach($numbers as $number) {
            foreach($combinations as $combination) {
                $result[] = $number . ',' . $combination;
            }
        }
    }

    return $result;
}

使用print_r输出数据时,它的执行速度非常慢:

$array = array_fill(0, pow(7,7), '');
$t = microtime(true);
echo '<pre>';
print_r($array);
echo '</pre>';
echo microtime(true) - $t;
// 0.75329303741455


$t = microtime(true);
echo '<pre>';
print_r( combine_all(array(1,2,3,4,5,6,7)) );
echo '</pre>';
echo microtime(true) - $t;
// 1.7037351131439


$t = microtime(true);
combine_all(array(1,2,3,4,5,6,7));
echo microtime(true) - $t;
//0.75869607925415

要限制项目编号,请使用array_slice功能:

combine_all(array_slice($numbers, 0, 7));

如果你真的想要一个递归函数,你可以这样做:

function combine_all(array $numbers, $cnt=null, $baseCombination=null) {
    if( $baseCombination === null ) {
        $cnt = count($numbers);
    }

    if( $cnt > 0 ) {
        $result = array();
        foreach($numbers as $number) {
            $combination = $number . ',' . $baseCombination;
            $result[] = $combination;
            $result = array_merge($result, combine_all($numbers, $cnt-1, $combination));
        }
        return $result;
    }

    return array();
}

但是it takes too much memory

答案 3 :(得分:-2)

我终于找到了一种方法来添加递归函数来创建给定数字的唯一组合:

$numbers = [1, 2, 3, 4, 5, 6, 7];

function subsetSumRecursive($numbers, $arraySize, $level = 1, $i = 0, $addThis = [])
{
    // If this is the last layer, use a different method to pass the number.
    if ($level == $arraySize) {
        $result = [];
        for (; $i < count($numbers); $i++) {
            $result[] = array_merge($addThis, array($numbers[$i]));
        }
        return $result;
    }

    $result = [];
    $nextLevel = $level + 1;
    for (; $i < count($numbers); $i++) {
        // Add the data given from upper level to current iterated number and pass
        // the new data to a deeper level.
        $newAdd = array_merge($addThis, array($numbers[$i]));
        $temp = subsetSumRecursive($numbers, $arraySize, $nextLevel, $i, $newAdd);
        $result = array_merge($result, $temp);
    }

    return $result;
}

echo "<pre>";
print_r(subsetSumRecursive($numbers, 7));
echo "</pre>";