Java 创建将n个用户放入k个组的所有可能方法

Java 创建将n个用户放入k个组的所有可能方法,java,algorithm,combinations,Java,Algorithm,Combinations,给定n个用户(u_1,u_2,…,u_n)和k个组(g_1,g_2,…,g_k),创建所有组的所有可能组合。基本上,每个组合最终都是一个映射,其中第一个整数是用户ID,第二个整数是组ID。例如,[(u_1,g_1),(u_2,g_1)…(u_n,g_1)]是一个可能的组合 将有k^n个组合 我搜索并看到了类似的问题,但它们确实有一些额外的条件不适用于我的问题。在我的例子中,每组都没有限制,也没有均匀性或均匀分布 您能推荐一种用Java实现这一点的快速方法吗 谢谢 到目前为止,我的努力: 我试图为

给定n个用户(u_1,u_2,…,u_n)和k个组(g_1,g_2,…,g_k),创建所有组的所有可能组合。基本上,每个组合最终都是一个映射,其中第一个整数是用户ID,第二个整数是组ID。例如,[(u_1,g_1),(u_2,g_1)…(u_n,g_1)]是一个可能的组合

将有k^n个组合

我搜索并看到了类似的问题,但它们确实有一些额外的条件不适用于我的问题。在我的例子中,每组都没有限制,也没有均匀性或均匀分布

您能推荐一种用Java实现这一点的快速方法吗

谢谢

到目前为止,我的努力: 我试图为每个用户的每个可能性创建一个for循环,但我面临的问题是无法定义for循环的数量

所以我切换到递归,但仍然坚持为函数的内部调用创建参数。不过还在努力

请注意,这不是“n选择k”。“n选择k”是指所有用户都相同,但这里的用户显然不相同



嗯。我为此创建了一个解决方案。基本上,这是一个动态规划问题。假设您已经为j用户和k位置创建了地图(组合)列表。要为j+1用户和k个位置创建,需要2个循环:对于每个Map,对于每个i=1到k,Map.put(user_j+1,k))。Is是递归和迭代的。递归,因为需要将旧映射传递给新迭代。就是这样。

所以你想要像k1,n1,k1,nN这样的地图。。kN,nN

  • 您将需要2个循环
  • 从循环分组开始。在每个组中,循环所有用户。。。在第二个循环中,将(组、用户)放入hashmap
  • 代码使用上述算法

  • 看起来我们有以下几点:

  • n
    不同的号码(用户)
  • k
    集合(组)
  • 目标是:

    • 用k集S_k查找所有k元组,使得对于1..k中的所有i,j,S_i和S_j的成对交集为空,且并集S_1。。S_k是集合
      1..n
    如果这是您想要的,那么我将递归地攻击它:

    • 如果n为0,则结果是1个空集合的k元组
    • 如果n为1,则结果为k元组,其中对于j=1..k的所有元素S_j,除了设置为{1}的第j个元素外,它是空集
    • 如果n是m,则计算m-1的元组列表。然后将列表复制k次,让第i个集合是第i个集合和{n}的并集。(注意,对于n=1,这只是先前规则的更一般形式)
    例如:

    n = 3, k = 2
        n = 2, k = 2
            n = 1, k = 2
                n = 0, k= 2
                result: [({},{})]
            result: [({1},{}), ({},{1})]
        result: [({1,2},{}), ({2},{1}),         // j=1, union 1st with {2}
                 ({1},{2}), ({},{1,2})]         // j=2, union 2nd with {2}
    result: [
        ({1,2,3},{}), ({2,3},{1}), ({1,3},{2}), ({3},{1,2}), // j=1, union 1st with {3}
        ({1,2},{3}), ({2},{1,3}), ({1},{2,3}), ({},{1,2,3})  // j=2, union 2nd with {3}
    ]
    

    这类问题的传统解决方案是使用递归:如果有n=0个用户,唯一可能的分组就是空组。否则,取出第一个用户并为其他n-1个用户生成解决方案。使用子问题的解决方案,通过将第一个用户分配到k个可能的组中的每个组来生成最终解决方案

    代码:

    import java.util.*;
    
    class Grouping {
        public static void main(String[] args) {
            List<?> groups = grouping(Arrays.asList(1,2,3), Arrays.asList(4,5,6,7));
            System.out.println(groups.size());
            System.out.println(groups);
        }
    
        static List<Map<Integer,Integer>> grouping(List<Integer> users, List<Integer> groups) {
            if (users.isEmpty()) {
                Map<Integer,Integer> empty = Collections.emptyMap();
                return Collections.singletonList(empty);
            } else {
                Integer user = users.get(0);
                List<Map<Integer,Integer>> subs = grouping(users.subList(1,users.size()), groups);
    
                List<Map<Integer,Integer>> solutions = new ArrayList<>();
                for (Integer group: groups) {
                    for (Map<Integer,Integer> sub : subs) {
                        Map<Integer,Integer> m = new HashMap<>(sub);
                        m.put(user, group);
                        solutions.add(m);
                    }
                }
                return solutions;
            }
        }
    }
    
    import java.util.*;
    班级分组{
    公共静态void main(字符串[]args){
    列表组=分组(Arrays.asList(1,2,3),Arrays.asList(4,5,6,7));
    System.out.println(groups.size());
    系统输出打印项次(组);
    }
    静态列表分组(列表用户、列表组){
    if(users.isEmpty()){
    Map empty=Collections.emptyMap();
    返回集合。singletonList(空);
    }否则{
    整数user=users.get(0);
    List subs=分组(users.subList(1,users.size()),groups);
    列表解决方案=新的ArrayList();
    对于(整数组:组){
    用于(地图子:子地图){
    Map m=新的HashMap(sub);
    m、 put(用户、组);
    添加(m);
    }
    }
    返回解决方案;
    }
    }
    }
    
    好的,这里有一个简单的想法。
    首先假设每个用户id在{0,…n-1}中,组id在{0,…k-1}中,我们可以稍后将这些数字映射回实际id。


    现在,你基本上想做的是迭代k进制中的所有n位数字,也就是说,你的问题中的每一位数字0都不能解释你是如何试图解决问题的;它现在读起来像是对代码的请求。请分享您尝试的实现,并解释它如何无法满足您的要求。您应该使用Prolog来处理以下内容:P但我想这是一个家庭作业,您至少应该展示您迄今为止尝试过的内容。是的,我们可能可以提供一种快速方法!但是你做了什么?为什么用户不完全相同?请显示问题说明。但这不会生成n^k个组合。。。如果你有2个组和3个用户,它会产生n*kIf。。告诉我如何创建超过2*3=6个排列?。如何得到2^3=8?这只创建了n*k个组,这是我到目前为止得到的。@最重要的是:每个用户都有k个选项,所以组合的总数是k^n@Simo你到底想要什么?根据你的问题,你想把
    映射成
    。这只在n*k中完成,最终有人理解了问题并给出了正确的解决方案:)。顺便说一句,在你发布之前我确实做到了,但看到这一点还是很高兴的。其他人不断给出错误的解决方案,当我指出它不正确时,他们有点生气了我看到你在发布后已经找到了一个解决方案,听起来你的解决方案与此非常相似。关于反应,我想“组合”这个词让很多人都不喜欢,因为它有一个精确的含义。是的,我也喜欢它。我的建议在实现方面看起来有些过分,但应该提供相同的结果和运行时复杂性。无论如何,递归是正确的方法,谢谢Joni。
    
    while (!combination.isMaxReached()) {
        combination.increment();
    }