找到三个置换列表的可能组合数

时间:2015-01-17 21:35:18

标签: algorithm math combinatorics

我正在为这项任务寻找解决方案:

有三个置换整数列表:

 index
 0 1 2 3
[2,4,3,1]
[3,4,1,2]
[1,2,4,3]

我想知道列表中有三个元组的组合数量。例如,将第二个列表向右旋转一个,将第三个列表向左旋转一个:

 0 1 2 3
[2,4,3,1]
 3 0 1 2
[2,3,4,1]
 1 2 3 0
[2,4,3,1]

会产生两种组合(2,2,2)(1,1,1)。我只对组合的数量感兴趣,而不是实际的组合本身。

列表的长度N始终相同。根据我的理解,至少有一个组合,最多为N.

我已经编写了一个命令式解决方案,使用了三个嵌套for循环,但是对于较大的问题大小(例如N> 1000),这很快变得无法忍受。

是否有比蛮力更有效的方法(尝试所有组合)?也许是一些聪明的算法或数学技巧?

编辑:
我正在改写这个问题,使其(希望)更加清晰:
我有3个列表的排列[1..N] 列表可以单独向左或向右旋转,直到某些索引的元素排成一行。在上面的例子中将是:
右旋转列表2乘1 左旋转列表3乘1 现在列对齐2和1 我还在上面的例子中添加了索引。请告诉我,它是否还不清楚。

到目前为止我的代码:

#include <iostream>

int
solve(int n, int * a, int * b, int * c)
{
  int max = 0;
  for (int i = 0; i < n; ++i) {
    int m = 0;
    for (int j = 0; j < n; ++j) {
      if (a[i] == b[j]) {
        for (int k = 0; k < n; ++k) {
          if (a[i] == c[k]) {
            for (int l = 0; l < n; ++l) {
              if (a[l] == b[(l+j) % n] && a[l] == b[(l+k) % n]) {
                ++m;
              }
            }
          }
        }
      }
    }
    if (m > max) {
      max = m;
    }
  }
  return max;
}

int
main(int argc, char ** argv)
{
  int n = 5;

  int a[] = { 1, 5, 4, 3, 2 };
  int b[] = { 1, 3, 2, 4, 5 };
  int c[] = { 2, 1, 5, 4, 3 };

  std::cout << solve(n, a, b, c) << std::endl;

  return 0;
}

2 个答案:

答案 0 :(得分:0)

您可以通过创建所有组合来实现: 0,0,0
0,0,1
0,1,0
0,1,1
1,0,0
1,0,1
1,1,0
1,1,1

每个0/1可以是你的数组

此代码可以帮助您创建上面的列表:

private static ArrayList<String> getBinaryArray(ArrayList<Integer> array){

//calculating the possible combinations we can get
int possibleCombinations = (int) Math.pow(2, array.size());

//creating an array with all the possible combinations in binary
String binary = "";
ArrayList<String> binaryArray = new ArrayList<String>();
for (int k = 0; k <possibleCombinations; k++) {

    binary = Integer.toBinaryString(k);

    //adding '0' as much as we need
    int len = (array.size() - binary.length());
    for (int w = 1; w<=len; w++) {
        binary = "0" + binary;
    }

    binaryArray.add(binary);
}

return binaryArray;
}

它也可以是0/1/2号码,其他号码可以是你得到的列表。

如果不太清楚,请告诉我

答案 1 :(得分:0)

这是一个有效的解决方案:

  1. 假设我们从第一个列表中选择了一个固定元素,我们希望将它与第二个和第三个列表中具有相同值的元素相匹配。它唯一地确定第二个和第三个列表的旋转(我们可以假设第一个列表永远不会旋转)。它给了我们一对两个整数:(第一个列表中该元素的位置减去它在第二个列表模N中的位置,第一个和第三个列表的位置相同)。

  2. 现在我们可以迭代第一个列表的所有元素并生成这些对。

  3. 答案是最常见的一对的发生次数。

  4. 如果我们使用标准排序来查找最频繁的对,或者如果我们使用基数排序或哈希表,则使用O(N),时间复杂度为O(N * log N)。