数组中所有可能的组合 - 递归?

时间:2014-02-04 15:47:49

标签: php arrays recursion permutation

我有一个问题超出了我的想法,希望有人可以提供帮助。我认为它可能必须通过递归和/或排列来解决,但我还不够(PHP)程序员。

$map[] = array("0", "1", "2", "3");
$map[] = array("4", "5", "6", "7");
$map[] = array("8", "9", "10", "11");
$map[] = array("12", "13", "14", "15");
$map[] = array("16", "17", "18", "19");
$map[] = array("20", "21", "22", "23");

$ map数组的最大长度限制为" 6"。

我正在寻找一种方法来制作所有可能的组合。以下是一些有效组合:

示例1:

$map[] = array("0", "1", "2", "3", "4", "5", "6", "7");
$map[] = array("8", "9", "10", "11");
$map[] = array("12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", );
$map[] = array("23");

示例2:

$map[] = array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23");

示例3:

$map[] = array("0", "1");
$map[] = array("2", "3", "4", "5", "6", "7", "8");
$map[] = array("9", "10", "11");
$map[] = array("12");
$map[] = array("13", "14", "15", "16", "17", "18", "19", "20");
$map[] = array("21", "22", "23");

每个地图数组中的值必须按升序排列,例如这个例子是无效的:

$map[] = array("0", "1", "4");
$map[] = array("3", "5");
etc...

希望这可以做到。

2 个答案:

答案 0 :(得分:0)

递归解决方案。

<?php
function combination($remaining, $current, $combinations) {
    $e = array_shift($remaining);
    $combinations[$current][] = $e;

    if(empty($remaining)) {
        print_r($combinations);
        return;
    }

    combination($remaining, $current, $combinations);
    // 6 Limit remove for all solutions
    if ($current < 6) {
        combination($remaining, $current + 1, $combinations);
    }
}


$remaining = range(0, 23);

combination($remaining, 0, array());

如果你想存储[0,23]的所有解决方案,你将度过一段美好的时光。

答案 1 :(得分:0)

由于您需要范围数字,我将问题简化为排列

这是一个shellscript(从终端作为node.js脚本执行),它计算你想要的范围:

#!/usr/bin/env nodejs

// Config
var blocksTotal     = 3;    // 6
var numbersTotal    = 6;    // 24
var perms           = [];   // Permutations

// Start the loop
(function divideHours(numbersToGo, blocksToGo, arr) {

    // What block is this? [1 .. 3]
    var block = blocksTotal - --blocksToGo;

    // Divide numbers
    if (block < blocksTotal)
        for (var hour = 0; hour <= numbersToGo; hour++) {
            if (block == 1) var arr = [];
            arr[block-1] = hour;
            divideHours(numbersToGo-hour, blocksToGo, arr);
        }
    // Last block? Assign rest of numbers
    else {
        perms.push(arr.concat([numbersToGo]));
        console.log(arr.concat([numbersToGo]).toString());
    }
})(numbersTotal, blocksTotal);

使用较小的范围和数字进行测试,您会得到以下排列:

  

0,0,6
  0,1,5
  0,2,4
  0,3,3
  0,4,2
  0,5,1
  0,6,0
  1,0,5
  1,1,4-
  1,2,3
  1,3,2
  1,4,1
  1,5,0
  2,0,4
  2,1,3
  2,2,2
  2,3,1
  2,4,0
  3,0,3
  3,1,2
  3,2,1
  3,3,0
  4,0,2
  4,1,1
  4,2,0
  5,0,1
  5,1,0
  6,0,0

看起来对吗? 现在尝试更大的数字,结果数组存储在perms

如果你明确想要数组中提到的每个数字,你可以使用一些计数器和数学来代替那种数组。例如: -
3,1,2 - &gt; [1,2,3],[4],[5,6]
2,0,4 - &gt; [1,2],[],[3,4,5,6]

这是一个使用6个块和24个数字的片段:

  

...
  7,2,2,10,0,3
  7,2,2,10,1,2
  7,2,2,10,2,1
  7,2,2,10,3,0
  7,2,2,11,0,2
  7,2,2,11,1,1
  7,2,2,11,2,0
  7,2,2,12,0,1
  7,2,2,12,1,0
  7,2,2,13,0,0
  7,2,3,0,0,12
  7,2,3,0,1,11
  7,2,3,0,2,10
  ...

..但这份名单是无止境的。