【问题标题】:All possible combinations in array - recursion?数组中所有可能的组合 - 递归?
【发布时间】:2014-02-28 16:27:07
【问题描述】:

我有个问题想不通,希望有人能提供帮助。我认为它可能必须通过递归和/或排列来解决,但我不是一个足够好的(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...

希望可以做到。

【问题讨论】:

  • 当你说,地图数组被限制为六个,那么你所有的有效示例都超过六个......
  • @omar-ali 例子是$map的第二维。
  • @omar-ali 他的意思是$map中只有6个索引(注意$map是一个数组)
  • 您能补充一下您的最终目标是什么吗?也许您的处理方法不正确,您实际上想做什么?
  • 我正在尝试找到最佳组。值(0、1、2、3 等)指的是时间范围内的“分数”(0 = 00:00 - 01:00、1 = 01:00 - 02:00 等)。我只能将这些分数分组和“总和”到 6 个“块”时间。我正在尝试找到一种方法,使组或“块”产生尽可能好的总和。

标签: php arrays recursion permutation


【解决方案1】:

递归解决方案。

<?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] 的所有解决方案,您会遇到麻烦。

【讨论】:

    【解决方案2】:

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

    这是一个 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 -> [1,2,3],[4],[5,6]
    2,0,4 -> [1,2],[],[3,4,5,6]

    这是一个使用 6 个块和 24 个数字的 sn-p:

    ...
    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
    ...

    ..但这个列表是无穷无尽的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      • 1970-01-01
      • 1970-01-01
      • 2013-01-17
      • 2016-03-20
      • 1970-01-01
      相关资源
      最近更新 更多