【问题标题】:How to select n numbers from n sets of different size?如何从 n 个不同大小的集合中选择 n 个数字?
【发布时间】:2014-08-24 12:28:15
【问题描述】:

我正在尝试实现一个应用程序。它需要以下逻辑。

Set1 {1,2,3,4}
Set2 {22,44}
Set3 {8,9,11}

我需要从每组中选择一个数字。所以总共会有3个数字。但是有很多组合。我的应用程序的每次运行都必须选择不同的组合以获得更好的复杂性。我的意思是

First run : 1 22 8
Second run : 1 44 9
And so on...

所以我需要找出不同大小的集合之间的所有组合。我知道在一组 {1,2,3,4} 中查找的方法。

我不知道任何数学算法。是否有任何逻辑可以在 Java、C 或 C++ 中完成。一般有什么想法吗?

编辑

预期输出是:

1 22 8
1 22 9
1 22 11
1 44 8 
1 44 9 
1 44 11
2 22 8
2 22 9
and so on

【问题讨论】:

  • 有一些函数可以获取随机数,所以你可以做的是从 0 到 n 随机一个数字(其中 n 是可能的集合数)并选择这个集合,这真的取决于你想要什么要做到这一点,您需要更具描述性。我的解决方案将为您提供相同的集合可能性,但它可能不是您想要的。
  • 如果我的标签有误,请告诉我。我会编辑它。我的目标只是想法而不是代码
  • 递归。你知道如何为一组做;对于 k >= 2 个集合,方法是从第一个集合中选择一个随机元素 x,然后用剩余的 k-1 个集合调用自己,从这些集合中找到一组 k-1 个代表,最后插入x 进入这个集合。
  • @cerkiewny 我会进一步编辑我的问题。
  • 我想我需要更多的咖啡,我只是用 Python 写了一个答案......然后意识到这是标记为 C++。

标签: java c++ c algorithm


【解决方案1】:

您可以通过使用com.google.common.collect.SetsJava 中的集合上使用笛卡尔积

举例

  Set<Integer> s1=new HashSet<Integer>();
  s1.add(1);s1.add(4);s1.add(5);

  Set<Integer> s2=new HashSet<Integer>();
  s2.add(2);s2.add(3);s2.add(6);

  Set<Integer> s3=new HashSet<Integer>();
  s3.add(7);s3.add(8);s3.add(8);

  Set<List<Integer>> set=Sets.cartesianProduct(s1,s2,s3);
  //Give type safety warning
  for(List<Integer> l:set){
      System.out.println(l);
  }

输出

[1, 2, 7]
[1, 2, 8]
[1, 3, 7]
[1, 3, 8]
....

注意

如果你想要精确的输出为1 2 7,你只需要Override toStringList的方法

【讨论】:

  • 这个逻辑比 N FOR LOOPS 好。你只使用了内置函数!!
  • Java 有 Sets 类吗?我猜这个来自 Google Guava。
【解决方案2】:

假设您只想输出可能的组合,您可以使用三个 for 循环非常简单地做到这一点。

for(int i = 0; i < set1.size; i++){
   for(int j = 0; j < set2.size; j++){
      for(int k = 0; k < set3.size; k++){
         System.out.println(set1.toArray()[i] + " " + set2.toArray()[j] + " " + set3.toArray()[k]);
         // toArray() represents the set as an array, allowing easy access to its indices
      }
   }
}

这将以一种简单的方式产生您列出的输出,您可能很容易看到它是如何工作的。对于来自set1set2 的固定值,输出来自set3 的所有可能性。然后从set2更改为另一个未使用的值,依此类推。

【讨论】:

    【解决方案3】:

    假设您不关心订单并且想要获得所有组合,您可以执行以下简单操作:

    for (auto it1 : set1)
    for (auto it2 : set2)
    for (auto it3 : set3)
    {
       //do stuff with *it1, *it2, *it3
       //e.g. printing them
       std::cout << *it1 << *it2 << *it3 << std::endl;
       //gives you exactly the listing you want
    }
    

    【讨论】:

    • 我不想操纵它们。只需要我在编辑中提到的列表
    • 列出它们需要迭代它们
    • 是的 :) 兰亭。已编辑
    • 是的 :) 它具有 (sizeofset1)*(sizeofset2)*(sizeofset3) 复杂性。我需要一个有效的方法
    • 没有更有效的方法。您必须遍历每个组合。
    猜你喜欢
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2011-10-10
    相关资源
    最近更新 更多