[英]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: 看起来我们有以下内容:
n
different numbers (users) n
不同的数字(用户) k
sets (groups) k
集(组) Objective is: 目标是:
1..n
1..n
If this is what you want, then I would attack this recursively: 如果这是你想要的,那么我会递归地攻击它:
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这样的地图。
- You will need 2 loops
你需要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...
在每个组中,循环遍历所有用户...并在第二个循环中,将(组,用户)放入散列映射...
- Code using the above algorithm.
使用上述算法的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.