[英]Create all possible ways of putting n users into k groups
给定n个用户(u_1,u_2,...,u_n)和k个组(g_1,g_2,...,g_k),创建所有组的所有可能组合。 基本上,最后,每个组合都是Map <Integer,Integer>,其中第一个Integer是用户ID,第二个Integer是组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))。 是递归和迭代。 递归,因为您需要将旧映射传递给新迭代。 而已。
这些问题的传统解决方案是使用递归:如果有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;
}
}
}
好的,这是一个简单的想法。
让我们首先假设每个user_id在{0,... n-1},并且group_id在{0,... k-1},我们可以稍后将这些数字映射回实际ID。
现在,您基本上想要做的是在Base k数字系统中迭代所有n位数字,即每个数字0 <= base <k。
所以,你从数字开始是0000 ... 00(n-neroes),你以kkkk .... kk(名义k的 n个数字)结束。 对于每个这样的数字,位置表示user_id,数字值是该用户的group_id。
所以,你需要实现的主要功能是表示这种n位数序列的类Combination
(尝试ArrayList
或简单的int[] array
),并正确实现increment()
操作(我认为递归是执行此实现的最佳方法) 。 可能你也可以使用方法isMaxReached()
来检查所有数字是否都是k
值。
然后你会有一个循环:
组合组合=新组合(); //用n -zeroes初始化
while (!combination.isMaxReached()) {
combination.increment();
}
如果您需要更多有关实施的详细信息,请与我们联系。
希望有所帮助。
看起来我们有以下内容:
n
不同的数字(用户) k
集(组) 目标是:
1..n
如果这是你想要的,那么我会递归地攻击它:
例:
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}
]
所以你想要像k1,n1,k1,nN .. kN,nN这样的地图。
- 你需要2个循环
- 首先循环组。 在每个组中,循环遍历所有用户...并在第二个循环中,将(组,用户)放入散列映射...
- 使用上述算法的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.