通过Javascript计算数组中的排列计数而不重复

时间:2014-03-23 12:42:27

标签: javascript arrays algorithm math

首先我有一个数组,如下所示:

var arr = [[2,3,4,5,6,7,8,9,10],
           [3,4,5,6,7,8,9,10,11],
           [4,5,6,7,8,9,10,11,12]]

不一定应该是这个数组,它可以是任何其他数组,它只是一个例子。所以我需要知道所有可能排列的数量,如下所示:

2,3,4
2,3,5
...
2,3,12

2,4,5
2,4,6
...
2,4,12

...
10,11,12

据我所知,这不是简单的排列。而且我也不需要所有这些组合,我只需要他们的计数,可能存在公式或类似的东西。在这个例子中,我知道答案是165.谢谢

2 个答案:

答案 0 :(得分:3)

假设订单必须增加:

var arr = [[2,3,4,5,6,7,8,9,10],
           [3,4,5,6,7,8,9,10,11],
           [4,5,6,7,8,9,10,11,12]];

function count(stack, history) {
  var counter = 0;
  history = history || [];
  stack[0].forEach(function(it) {
    if (! history.length || history[history.length -1] < it) {
      if (stack[1]) {
        counter += count(stack.slice(1), history.concat([it]));
      } else  {
        counter++;
      }
    }
  });
  return counter;
}

console.log(count(arr)); //165

答案 1 :(得分:0)

这是一个有趣的数学问题。我认为你所指的是组合而不是排列。我先把javascript放在这里。数学如下。

<script type="text/javascript">
var arr = new Array();
arr[0] = new Array(2,3,4,5,6,7,8,9,10);
arr[1] = new Array(3,4,5,6,7,8,9,10,11);
arr[2] = new Array(4,5,6,7,8,9,10,11,12);


function countcombinations() {
    var history = new Array();

    for (var i=0;i<arr[0].length;i++) {
        for (var j=0;j<arr[1].length;j++) {  
            for (var k=0;k<arr[2].length;k++) {
                if (arr[0][i] == arr[1][j] || arr[0][i] == arr[2][k] || arr[1][j] == arr[2][k]) {
                } else {
                    // If all are different, consider this set as candidate
                    var found = false;

                    history.forEach(function(entry) {
                        if (
                            // The various possible sequences for comparison
                            (arr[0][i] == entry[0] && arr[1][j] == entry[1] && arr[2][k] == entry[2]) ||
                            (arr[0][i] == entry[0] && arr[1][j] == entry[2] && arr[2][k] == entry[1]) ||
                            (arr[0][i] == entry[1] && arr[1][j] == entry[0] && arr[2][k] == entry[2]) ||
                            (arr[0][i] == entry[1] && arr[1][j] == entry[2] && arr[2][k] == entry[0]) ||
                            (arr[0][i] == entry[2] && arr[1][j] == entry[0] && arr[2][k] == entry[1]) ||
                            (arr[0][i] == entry[2] && arr[1][j] == entry[1] && arr[2][k] == entry[0])
                        ) found = true;
                    });

                    // If not found, add to history
                    if (!found) history[history.length] = new Array(arr[0][i], arr[1][j], arr[2][k]);                   
                }
            }
        }
    }  

    alert ("Count: " + history.length);
}

countcombinations(); // Gives 165

</script>

在数学上,问题可以通过迭代第一组并考虑每种的可能性来解决。这就是上面javascript代码中的算法。元素的顺序无关紧要。每次找到新的唯一组合时,它会将此组合附加到历史记录中。为了好玩,您可以尝试使用上面的代码并应用下面的数学来进一步理解它。

对于数学的人类方法,让我们考虑第一组并使用(X,Y,Z)来表示所选择的三个数字。每组中的数字需要按递增顺序排列,后续组中的最小数字也需要按递增顺序排列。给我们的阵列符合这些条件。所以,对于第一组:

[2,3,4,5,6,7,8,9,10]

当X = 2,即(2,Y,Z)时,有两种可能性需要考虑:

Y = 3
Y > 3

如果Y = 3,则Z有9种可能性(4到12)。

如果Y&gt; 3,那么如果Z <在图12中,(Y,Z)具有8C2(8选2)或28种可能的组合。 如果Z = 12,则(Y,12)具有8种可能的组合。因此:

X = 2, Y = 3, Z > 3 : 9 combinations
X = 2, Y > 3, Z < 12 : 8C2 = 28 combinations
X = 2, Y > 3, Z = 12 : 8 combinations
In short, there are 45 possible combinations where any of the numbers is 2.

唷!继续,从数字3到9,您可以重复使用上述两个条件:Z&lt; 12或Z = 12.您将看到如下所示的模式:

X = 3, Y > 3, Z < 12: 8C2 = 28 combinations
X = 3, Y > 3, Z = 12: 8 combinations

X = 4, Y > 4, Z < 12: 7C2 = 21 combinations
X = 4, Y > 4, Z < 12: 7 combinations

...

X = 9, Y > 9, Z < 12: 2C2 = 1  combination
X = 9, Y > 9, Z = 12: 2 combinations

最后,当X = 10时,只有一种可能性是(10,11,12)。

因此,组合的数量(具有良好的递减模式)是:

X = 2: 9 + 8C2 + 8 = 45
X = 3: 8C2 + 8 = 36
X = 4: 7C2 + 7 = 28
X = 5: 6C2 + 6 = 21
X = 6: 5C2 + 5 = 15
X = 7: 4C2 + 4 = 10
X = 8: 3C2 + 3 = 6
X = 9: 2C2 + 2 = 3
X = 10: 1 = 1
TOTAL: 165