查找两个数组之间的所有可能值组合

时间:2011-05-19 12:50:32

标签: c# algorithm combinatorics

我有两个字符串数组,不一定长度相同,我想找到数组中两个值之间所有可能的“组合”组合,而不是从任何一个数组重复。
例如,给定阵列:
{“A1”,“A2”,“A3”}
{“B1”,“B2”}
我想要的结果是以下几组:
{(“A1”,“B1”),(“A2”,“B2”)}
{(“A1”,“B1”),(“A3”,“B2”)}
{(“A1”,“B2”),(“A2”,“B1”)}
{(“A1”,“B2”),(“A3”,“B1”)}
{(“A2”,“B1”),(“A3”,“B2”)}
{(“A2”,“B2”),(“A3”,“B1”)}

我的总体方向是创建递归函数,该函数将两个数组作为参数并一次删除每个“选定”的字符串,调用自身直到任一数组为空,但是我有点担心性能问题(我需要在大约1000对字符串数组上运行此代码。) 任何人都可以指导我采用有效的方法来做到这一点吗?

7 个答案:

答案 0 :(得分:9)

将两个数组视为表的一边可能是有益的:

        A1      A2      A3
---+-------+-------+-------+
B1 | B1,A1 | B1,A2 | B1,A3 |
---+-------+-------+-------+
B2 | B2,A1 | B2,A2 | B2,A3 |
---+-------+-------+-------+

这意味着一个循环嵌套在另一个循环中,一个循环用于行,另一个循环用于列。这将为您提供初始的一组对:

{B1,A1} {B1,A2} {B1,A3} {B2,A1} {B2,A2} {B2,A3}

然后是建立初始集的组合的问题。您可以使用行和列的成对集来类似地可视化组合:

      B1,A1 B1,A2 B1,A3 B2,A1 B2,A2 B2,A3
-----+-----+-----+-----+-----+-----+-----+
B1,A1|     |  X  |  X  |  X  |  X  |  X  |
-----+-----+-----+-----+-----+-----+-----+
B1,A2|     |     |  X  |  X  |  X  |  X  |
-----+-----+-----+-----+-----+-----+-----+
B1,A3|     |     |     |  X  |  X  |  X  |
-----+-----+-----+-----+-----+-----+-----+
B2,A1|     |     |     |     |  X  |  X  |
-----+-----+-----+-----+-----+-----+-----+
B2,A2|     |     |     |     |     |  X  |
-----+-----+-----+-----+-----+-----+-----+
B2,A3|     |     |     |     |     |     |
-----+-----+-----+-----+-----+-----+-----+

同样可以通过一对嵌套循环来完成(提示:你的内循环的范围将由外循环的值决定)。

答案 1 :(得分:2)

非常简单的方法是

string[] arr = new string[3];
        string[] arr1 = new string[4];
        string[] jointarr = new string[100];

        for (int i = 0; i < arr.Length; i++)
        {
            arr[i] = "A" + (i + 1);
        }

        for (int i = 0; i < arr1.Length; i++)
        {
            arr1[i] = "B" + (i + 1);
        }

        int k=0;
        for (int i = 0; i < arr.Length; i++)
        {
            for (int j = 0; j < arr1.Length; j++)
            {
                jointarr[k] = arr[i] + " " + arr1[j];
                k++;
            }
        }

答案 2 :(得分:2)

您的问题等同于以下问题:

问题陈述:
给定两个大小为A的{​​{1}},大小为n的{​​{1}},其中Bm
n <= m
A = [0, 1, 2, ..., n - 1]B = [0, 1, 2, ..., m - 1]查找所有可能的injective and non-surjective mappingsOne possible injective and non-surjective mapping

<强>解决方案
由于A的大小较小,在一次映射中,对应的数量等于A的大小,即n。

然后我们生成B的所有可能的排列,以便每个排列中的起始n个元素可以与A中的元素一一对应。

前几个排列和映射如下: Permutation 1 Permutation 2 Permutation 3 Permutation 4

<强>实施

A

答案 3 :(得分:0)

它的问题不完全相同,但是我对以下问题做了一个解决方案,可能是一个不错的起点:

Array of array combinations

答案 4 :(得分:0)

关于本网站上两个列表的组合,有很多问题(和答案)(见边栏)。如果我理解正确,你的用例似乎只是表面上不同。

拥有方法

是不够的
IEnumerable<Tuple<string, string>> Combinations(
  IEnumerable<string> list1, 
  IEnumerable<string> list2) {}

(已经在'重复'中以各种形式和大小存在)然后按照这些步骤使用它(作业=你填写详细信息):

迭代列表1和列表的所有组合;清单2(使用类似上面的内容)和

  • 按当前组合的第一个元素过滤列表1
  • 按当前组合的第二个元素过滤列表2
  • 将当前组合与已过滤列表的所有可能组合(使用类似上述方法)相结合

答案 5 :(得分:0)

如果我正确理解您的问题,可以使用以下方法派生所有组合:

  • 从A
  • 中选择了2个不同的元素{A_i, A_j}
  • 从B中选择了2个不同的元素{B_k, B_l}
  • 与这些元素{ (A_i, B_k), (A_j, B_l) }, { (A_i, B_l), (A_j, B_k) }进行2次组合。

通过A和B中2个元素子集的所有组合,您可以获得所需的所有组合。

|A| * (|A| - 1) * |B| * (|B| - 1) / 2种组合。

易于实现4循环:

for i = 1 ... |A|
  for j = i+1 ... |A|
    for k = 1 ... |B|
      for l = k+1 ... |B|
        make 2 combinations {(A_i, B_k),(A_j, B_l)}, {(A_i, B_l), (A_j, B_k)}

答案 6 :(得分:0)

当我看到一个填字游戏风格的拼图时,我看到了这个挑战,其中每个方格都有一个数字,你必须找到哪个字母对应于哪个数字才能使单词正确。知道我已经触及已经给出的答案,我将尝试总结问题,并说明如何以递归方式解决问题。

在x字的情况下,较小的数组A是一系列数字,而大数组B包含字母表的字母。问题是将每个数字分配给一个字母,并找到所有可能的组合。一般来说,我们有:

A={1,2,...m} and B={1,2,....n}     n>=m

对于对A(i)B(j),每个可能的结果可以写为具有m个元素的数组C,其中元素i携带值j。排列的总数,即C阵列,是n(n-1)......(n-m + 1)或更整齐地写:n!/(m + 1)!

这个数字来自于认为当A的第一个元素与B中的任何元素配对时,A的第二个元素可以与任何元素配对,除了所采用的元素。第一个,依此类推。

我们可以通过以下 - code:

来实现这一目标
for i= 1 to n
   C(1)=B(i)
   for j= 1 to n-1
      C(2)=B'(j)        '  B' is B with element i removed
         .........
          for x = 1 to n-m
             C(m)=B'''(x)   'B is now reduced with (m-1) elements
          next x

我使用基于1的数组来实现直观性。

这段代码对于任意长度的A都不起作用,并且为大m编写会很麻烦,所以我们最好用一个可以调用自身的过程AllPairs进行递归:

   AllPairs (A,B,C)
    if Size(A)>1             ' check no of elements in A        
      for i=1 to Size(B)
       C(Size(C)-Size(A)+1)= B(i)
       A'=Remove element 1 from A
       B'=Remove element i from B
       Call AllPairs(A',B',C)     'recursive call
      Next i
    else                          ' only one element in A
      for j=1 to Size(B)
      C(Size(C)) = B(i)  'looping last element in C through all unused in B
      Collect.ADD(C)      'collect C-arrays here for later use
      Next j                 
  End AllPairs

请注意,C最初是一个与A大小相同的空数组(也可以是A的副本)。 C保持相同的大小,而A和B连续减少,直到A只包含一个元素,递归调用结束。这样做会。也许(在所有方面),这类似于代码Jingie Zheng的答案 - (我不能告诉)。我的目的是尝试提供一个简单直观的伪代码版本。可以在VB here.

中实现此解决方案