简体   繁体   English

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

[英]Create all possible ways of putting n users into k groups

Given n users (u_1, u_2,..., u_n) and k groups (g_1, g_2, ..., g_k), create all possible combinations of all groups. 给定n个用户(u_1,u_2,...,u_n)和k个组(g_1,g_2,...,g_k),创建所有组的所有可能组合。 basically, in the end, each combination is a Map<Integer,Integer>, where the first Integer is user ID, and the second Integer is group ID.For example, [(u_1,g_1), (u_2,g_1)....,(u_n, g_1)] is one possible combination. 基本上,最后,每个组合都是Map <Integer,Integer>,其中第一个Integer是用户ID,第二个Integer是组ID。例如,[(u_1,g_1),(u_2,g_1).. ..,(u_n,g_1)]是一种可能的组合。

There will be k^n combinations. 将有k ^ n种组合。

I searched and saw similar problems, but they do have some extra conditions that do not apply for my problem. 我搜索并看到了类似的问题,但他们确实有一些额外的条件不适用于我的问题。 In my case, there is no limit in each group, and there is no evenness or uniform distribution. 在我的情况下,每组没有限制,并且没有均匀或均匀分布。

Can you suggest a quick way to do this in Java? 你能用Java快速建议吗?

Thanks 谢谢

My tries so far: I tried to create a for loop for each possibility for each user, but I face the problem that I cannot define the number of for loops. 到目前为止我的尝试:我试图为每个用户的每种可能性创建一个for循环,但我面临的问题是我无法定义for循环的数量。

So I switched to recursion, but stuck at creating parameters for inside calls to the functions. 所以我切换到递归,但坚持为内部调用函数创建参数。 Still working on it though. 尽管如此,仍然在努力。

Please, also note that this is not "n choose k". 请注意,这不是“n选择k”。 "n choose k" is when all users are identical, but here users are obviously not identical. “n选择k”是指所有用户都相同,但这里的用户显然不相同。


OK. 好。 I created a solution for this. 我为此创建了一个解决方案。 Basically, it's a dynamic programming problem. 基本上,这是一个动态编程问题。 Assume you have created a List of Maps (combinations) for j users and k locations. 假设您已为j个用户和k个位置创建了一个地图列表(组合)。 TO create for j+1 users and k locations, need 2 loop: for each Map, for each i=1 to k, Map.put(user_j+1, k)). 要为j + 1个用户和k个位置创建,需要2个循环:对于每个Map,对于每个i = 1到k,Map.put(user_j + 1,k))。 Is is both recursive and iterative. 是递归和迭代。 Recursive because you need to pass the old maps to the new iterations. 递归,因为您需要将旧映射传递给新迭代。 That's it. 而已。

The traditional solution to these kinds of problems is using recursion: If there are n = 0 users the only grouping possible is the empty group. 这些问题的传统解决方案是使用递归:如果有n = 0个用户,则唯一可能的分组是空组。 Otherwise, take out the first user and generate the solution for the other n-1 users. 否则,取出第一个用户并为其他n-1个用户生成解决方案。 Using the solution for the subproblem, generate the final solutions by assigning the first user to each of the k possible groups. 使用子问题的解决方案,通过将第一个用户分配给k个可能的组中的每一个来生成最终解决方案。

In code: 在代码中:

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;
        }
    }
}

Ok, here is simple idea. 好的,这是一个简单的想法。
Lets first assume that each user_id is in {0, ... n-1}, and group_id is in {0, ... k-1}, we can map this numbers back to real ids later. 让我们首先假设每个user_id在{0,... n-1},并且group_id在{0,... k-1},我们可以稍后将这些数字映射回实际ID。

Now, what you basically want to do is to iterate thru all n-digit numbers in Base k numeral system, ie where each digit 0 <= base < k. 现在,您基本上想要做的是在Base k数字系统中迭代所有n位数字,即每个数字0 <= base <k。
So, you start with number is 0000...00 (n-zeroes) and you end with kkkk....kk (n digits of nominal k ). 所以,你从数字开始是0000 ... 00(n-neroes),你以kkkk .... kk(名义k的 n个数字)结束。 For each such number the position indicates user_id and digit value is this user's group_id. 对于每个这样的数字,位置表示user_id,数字值是该用户的group_id。

So, the main workhorse you need to implement is the class Combination representing such n-digits sequence(try ArrayList or simple int[] array ), with increment() operation implemented correctly (I imagine recursion is the best way to do this implementation). 所以,你需要实现的主要功能是表示这种n位数序列的类Combination (尝试ArrayList或简单的int[] array ),并正确实现increment()操作(我认为递归是执行此实现的最佳方法) 。 May be you could also have method isMaxReached() to check if all digits are of value k . 可能你也可以使用方法isMaxReached()来检查所有数字是否都是k值。

Then you would have a single loop : 然后你会有一个循环:

Combination combination = new Combination(); 组合组合=新组合(); // initialized with n -zeroes //用n -zeroes初始化

while (!combination.isMaxReached()) {
    combination.increment();
}

Please let me know if you would need more details on implementation. 如果您需要更多有关实施的详细信息,请与我们联系。

Hope that helps. 希望有所帮助。

It looks like we have the following: 看起来我们有以下内容:

  1. n different numbers (users) n不同的数字(用户)
  2. k sets (groups) k集(组)

Objective is: 目标是:

  • Find all the k-tuples with k sets S_k, such that for all i,j in 1..k the pairwise intersection of S_i and S_j is empty and the union S_1 .. S_k is the set 1..n 找到所有具有k个集合S_k的k元组,这样对于所有i,j在1..k中,S_i和S_j的成对交集为空,并且并集S_1 .. S_k是集合1..n

If this is what you want, then I would attack this recursively: 如果这是你想要的,那么我会递归地攻击它:

  • If n is 0, then the result is 1 k-tuple of empty sets. 如果n为0,则结果为空集的1 k元组。
  • If n is 1, then the results are k tuples, where for all elements S_j with j = 1..k it is the empty set except for the j-th element that is set {1}. 如果n为1,则结果为k元组,其中对于j = 1..k的所有元素S_j,除了设置为{1}的第j个元素之外,它是空集。
  • If n is m, then compute the list of tuples for m-1. 如果n是m,则计算m-1的元组列表。 Then replicate the list k times, and let the i-th set be the union of the i-th set and {n}. 然后复制列表k次,让第i个集合成为第i个集合和{n}的并集。 (Note that this is just a more general form of the previous rule for n=1). (请注意,这只是n = 1的先前规则的更一般形式)。

Example: 例:

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}
]

So u want maps like k1,n1, k1,nN .. kN,nN.. 所以你想要像k1,n1,k1,nN .. kN,nN这样的地图。

  1. You will need 2 loops 你需要2个循环
  2. Start by looping the groups . 首先循环组。 In each group, loop over all the users... and in the second loop , put(group,user) in a hashmap... 在每个组中,循环遍历所有用户...并在第二个循环中,将(组,用户)放入散列映射...
  3. Code using the above algorithm. 使用上述算法的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 K个项目可以在N个插槽中排列的所有可能方式 - all possible ways in which K items can be arranged in N slots 以所有可能的方式将列表拆分为 n 个子列表 - Split a list into n sublists in all possible ways 大小为 n 的所有可能的 k 个列表组合 - All Possible k combinations of list with size n 如何从大小为 n 的数组(无重复)中创建大小为 k 的所有可能子集? - How to create all possible subsets of size k from an array of size n (no repeats)? 创建大小为n的布尔数组的所有可能方式? - Creating all possible ways of a boolean array of size n? 找到你可以上n阶梯的所有方法,如果你可以一次采取k步,使k &lt;= n - Find all the ways you can go up an n step staircase if you can take k steps at a time such that k <= n 是否有一种方法会为n选择k返回所有可能的组合? - Is there a method returns all possible combinations for n choose k? 编程一个递归方法以计算n个元素和k个组的组数 - Programming a recursive method to calculate number of groups with n elements and k groups 来自一组长度(字符数组)的长度为k(长度为k的字符串)的所有可能置换长度n动态编程解决方案 - All possible permutations of length k (k legth string ) from a set (array of chars) length n dynamic programming solution 将N人分成K组:为什么这个算法的大O是O(N^2 * K)? - Divide N people into K groups: Why is the big O of this algorithim O(N^2 * K)?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM