Java 如何按交集过滤集合?
我需要通过集合的交集合并集合,并用这样的签名编写一个函数Java 如何按交集过滤集合?,java,algorithm,set,Java,Algorithm,Set,我需要通过集合的交集合并集合,并用这样的签名编写一个函数 Collection<Set<Integer>> filter(Collection<Set<Integer>> collection); 在本例中,我们可以看到集合1、3和5相交。我们可以将它重写为一个新的集合{1,2,3,5}。另外,我们有两个集合也有交点。它们是2和4,我们可以创建一个新集合{4,7}。输出结果将是两个集合的集合:{1,2,3,5}和{4,7} 我不知道从哪一点开始解
Collection<Set<Integer>> filter(Collection<Set<Integer>> collection);
在本例中,我们可以看到集合1
、3
和5
相交。我们可以将它重写为一个新的集合{1,2,3,5}
。另外,我们有两个集合也有交点。它们是2
和4
,我们可以创建一个新集合{4,7}
。输出结果将是两个集合的集合:{1,2,3,5}
和{4,7}
我不知道从哪一点开始解决这个问题 这将解决您的用例。它可能会以一种更有效的方式实施,但我想这应该给你一个开始的想法:
private static Collection<Set<Integer>> mergeIntersections(Collection<Set<Integer>> collection) {
Collection<Set<Integer>> processedCollection = mergeIntersectionsInternal(collection);
while (!isMergedSuccessfully(processedCollection)) {
processedCollection = mergeIntersectionsInternal(processedCollection);
}
return processedCollection;
}
private static boolean isMergedSuccessfully(Collection<Set<Integer>> processedCollection) {
if (processedCollection.size() <= 1) {
return true;
}
final Set<Integer> mergedNumbers = new HashSet<>();
int totalNumbers = 0;
for (Set<Integer> set : processedCollection) {
totalNumbers += set.size();
mergedNumbers.addAll(set);
}
if (totalNumbers > mergedNumbers.size()) {
return false;
}
return true;
}
private static Collection<Set<Integer>> mergeIntersectionsInternal(Collection<Set<Integer>> collection) {
final Collection<Set<Integer>> processedCollection = new ArrayList<>();
// ITERATE OVER ALL SETS
for (final Set<Integer> numberSet : collection) {
for (final Integer number : numberSet) {
boolean matched = false;
// ITERATE OVER ALL PROCESSED SETS COLLECTION
for (final Set<Integer> processedSet : processedCollection) {
// CHECK OF THERE IS A MATCH
if (processedSet.contains(number)) {
matched = true;
// MATCH FOUND, MERGE THE SETS
processedSet.addAll(numberSet);
// BREAK OUT OF PROCESSED COLLECTION LOOP
break;
}
}
// IF NOT MATCHED THEN ADD AS A COLLECTION ITEM
if (!matched) {
processedCollection.add(new HashSet<>(numberSet));
}
}
}
return processedCollection;
}
私有静态集合(集合集合){
Collection processedCollection=mergeIntersectionsInternal(集合);
而(!isMergedSuccessfully(processedCollection)){
processedCollection=mergeIntersectionsInternal(processedCollection);
}
返回已处理的集合;
}
私有静态布尔值isMergedSuccessfully(Collection processedCollection){
if(processedCollection.size()mergedNumber.size()){
返回false;
}
返回true;
}
私有静态集合mergeIntersectionsInternal(集合集合){
最终集合processedCollection=new ArrayList();
//迭代所有集合
用于(最终设置编号集合:集合){
for(最终整数:numberSet){
布尔匹配=假;
//迭代所有已处理的集合集合
对于(最终集processedSet:processedCollection){
//检查是否有火柴
if(processedSet.contains(number)){
匹配=真;
//找到匹配项,合并集合
processedSet.addAll(numberSet);
//中断已处理的收集循环
打破
}
}
//如果不匹配,则添加为集合项
如果(!匹配){
add(新哈希集(numberSet));
}
}
}
返回已处理的集合;
}
它是这样执行的:
public static void main(String[] args) {
final Collection<Set<Integer>> collection = new ArrayList<>();
final Set<Integer> set1 = new HashSet<>();
set1.add(1);
set1.add(2);
set1.add(3);
collection.add(set1);
final Set<Integer> set2 = new HashSet<>();
set2.add(4);
collection.add(set2);
final Set<Integer> set3 = new HashSet<>();
set3.add(1);
set3.add(5);
collection.add(set3);
final Set<Integer> set4 = new HashSet<>();
set4.add(4);
set4.add(7);
collection.add(set4);
final Set<Integer> set5 = new HashSet<>();
set5.add(3);
set5.add(5);
collection.add(set5);
System.out.println(mergeIntersections(collection));
}
publicstaticvoidmain(字符串[]args){
最终集合集合=新的ArrayList();
final Set set1=新的HashSet();
set1.添加(1);
set1.添加(2);
set1.添加(3);
集合。添加(set1);
final Set set2=新的HashSet();
set2.添加(4);
集合。添加(set2);
final Set set3=新的HashSet();
set3.添加(1);
set3.添加(5);
集合。添加(set3);
final Set set4=新的HashSet();
set4.添加(4);
set4.添加(7);
集合。添加(set4);
final Set set5=新的HashSet();
set5.添加(3);
set5.添加(5);
集合。添加(set5);
System.out.println(合并交叉点(集合));
}
我的行动开始了。它从输入集合中删除所有集合,这可以通过先制作副本轻松修复。它不会修改输入集合中的每个集合。在我的实现中,Ajay的主方法打印[[1,2,3,5],[4,7]]
Collection<Set<Integer>> filter(Collection<Set<Integer>> collection) {
Collection<Set<Integer>> mergedSets = new ArrayList<>(collection.size());
// for each set at a time, merge it with all sets that intersect it
while (! collection.isEmpty()) {
// take out the first set; make a copy as not to mutate original sets
Set<Integer> currentSet = new HashSet<>(removeOneElement(collection));
// find all intersecting sets and merge them into currentSet
// the trick is to continue merging until we find no intersecting
boolean mergedAny;
do {
mergedAny = false;
Iterator<Set<Integer>> it = collection.iterator();
while (it.hasNext()) {
Set<Integer> candidate = it.next();
if (intersect(currentSet, candidate)) {
it.remove();
currentSet.addAll(candidate);
mergedAny = true;
}
}
} while (mergedAny);
mergedSets.add(currentSet);
}
return mergedSets;
}
private static Set<Integer> removeOneElement(Collection<Set<Integer>> collection) {
Iterator<Set<Integer>> it = collection.iterator();
Set<Integer> element = it.next();
it.remove();
return element;
}
/** @return true if the sets have at least one element in common */
private static boolean intersect(Set<Integer> leftSet, Set<Integer> rightSet) {
// don’t mutate, take a copy
Set<Integer> copy = new HashSet<>(leftSet);
copy.retainAll(rightSet);
return ! copy.isEmpty();
}
集合过滤器(集合){
Collection mergedSets=newarraylist(Collection.size());
//一次为每个集合合并与其相交的所有集合
而(!collection.isEmpty()){
//取出第一组;复制一份,以免改变原始组
Set currentSet=newhashset(removeOneElement(collection));
//找到所有相交集并将它们合并到currentSet中
//诀窍是继续合并,直到找不到相交
布尔合并丹尼;
做{
mergedAny=false;
Iterator it=collection.Iterator();
while(it.hasNext()){
Set candidate=it.next();
if(相交(当前集,候选)){
it.remove();
currentSet.addAll(候选);
mergedAny=true;
}
}
}while(mergedAny);
mergedSets.add(currentSet);
}
返回合并集;
}
私有静态集合removeOneElement(集合){
Iterator it=collection.Iterator();
Set element=it.next();
it.remove();
返回元素;
}
/**@如果集合至少有一个共同元素,则返回true*/
私有静态布尔相交(设置leftSet,设置rightSet){
//不要变异,复制一份
Set copy=新哈希集(leftSet);
副本。保留(右集);
return!copy.isEmpty();
}
解决此问题的一种优雅方法是使用无向图,将输入集中的一个元素与同一集中的至少一个其他元素连接起来,然后查找连接的组件
因此,您的示例的图形表示为:
由此我们可以很容易地推断出连接的成分:{1,2,3,5}和{4,7}
这是我的密码:
Collection<Set<Integer>> filter(Collection<Set<Integer>> collection) {
// Build the Undirected Graph represented as an adjacency list
Map<Integer, Set<Integer>> adjacents = new HashMap<>();
for (Set<Integer> integerSet : collection) {
if (!integerSet.isEmpty()) {
Iterator<Integer> it = integerSet.iterator();
int node1 = it.next();
while (it.hasNext()) {
int node2 = it.next();
if (!adjacents.containsKey(node1)) {
adjacents.put(node1, new HashSet<>());
}
if (!adjacents.containsKey(node2)) {
adjacents.put(node2, new HashSet<>());
}
adjacents.get(node1).add(node2);
adjacents.get(node2).add(node1);
}
}
}
// Run DFS on each node to collect the Connected Components
Collection<Set<Integer>> result = new ArrayList<>();
Set<Integer> visited = new HashSet<>();
for (int start : adjacents.keySet()) {
if (!visited.contains(start)) {
Set<Integer> resultSet = new HashSet<>();
Deque<Integer> stack = new ArrayDeque<>();
stack.push(start);
while (!stack.isEmpty()) {
int node1 = stack.pop();
visited.add(node1);
resultSet.add(node1);
for (int node2 : adjacents.get(node1)) {
if (!visited.contains(node2)) {
stack.push(node2);
}
}
}
result.add(resultSet);
}
}
return result;
}
集合过滤器(集合){
//构建表示为邻接列表的无向图
映射邻接项=新HashMap();
for(设置整数集:集合){
如果(!integerSet.isEmpty()){
迭代器it=integerSet.Iterator();
int node1=it.next();
while(it.hasNext()){
int node2=it.next();
if(!adjances.containsKey(node1)){
put(node1,newhashset());
}
if(!adjances.containsKey(node2)){
put(node2,newhashset());
}
获取(node1)、添加(node2);
获取(node2)、添加(node1);
}
}
}
//在每个节点上运行DFS以收集连接的组件
Collection<Set<Integer>> filter(Collection<Set<Integer>> collection) {
// Build the Undirected Graph represented as an adjacency list
Map<Integer, Set<Integer>> adjacents = new HashMap<>();
for (Set<Integer> integerSet : collection) {
if (!integerSet.isEmpty()) {
Iterator<Integer> it = integerSet.iterator();
int node1 = it.next();
while (it.hasNext()) {
int node2 = it.next();
if (!adjacents.containsKey(node1)) {
adjacents.put(node1, new HashSet<>());
}
if (!adjacents.containsKey(node2)) {
adjacents.put(node2, new HashSet<>());
}
adjacents.get(node1).add(node2);
adjacents.get(node2).add(node1);
}
}
}
// Run DFS on each node to collect the Connected Components
Collection<Set<Integer>> result = new ArrayList<>();
Set<Integer> visited = new HashSet<>();
for (int start : adjacents.keySet()) {
if (!visited.contains(start)) {
Set<Integer> resultSet = new HashSet<>();
Deque<Integer> stack = new ArrayDeque<>();
stack.push(start);
while (!stack.isEmpty()) {
int node1 = stack.pop();
visited.add(node1);
resultSet.add(node1);
for (int node2 : adjacents.get(node1)) {
if (!visited.contains(node2)) {
stack.push(node2);
}
}
}
result.add(resultSet);
}
}
return result;
}
public class UnionFind {
Set<Integer> all = new HashSet<>();
Set<Integer> representants = new HashSet<>();
Map<Integer, Integer> parents = new HashMap<>();
public void union(int p0, int p1) {
int cp0 = find(p0);
int cp1 = find(p1);
if (cp0 != cp1) {
int size0 = parents.get(cp0);
int size1 = parents.get(cp1);
if (size1 < size0) {
int swap = cp0;
cp0 = cp1;
cp1 = swap;
}
parents.put(cp0, size0 + size1);
parents.put(cp1, cp0);
representants.remove(cp1);
}
}
public int find(int p) {
Integer result = parents.get(p);
if (result == null) {
all.add(p);
parents.put(p, -1);
representants.add(p);
result = p;
} else if (result < 0) {
result = p;
} else {
result = find(result);
parents.put(p, result);
}
return result;
}
public Collection<Set<Integer>> getGroups() {
Map<Integer, Set<Integer>> result = new HashMap<>();
for (Integer representant : representants) {
result.put(representant, new HashSet<>(-parents.get(representant)));
}
for (Integer value : all) {
result.get(find(value)).add(value);
}
return result.values();
}
public static Collection<Set<Integer>> filter(Collection<Set<Integer>> collection) {
UnionFind groups = new UnionFind();
for (Set<Integer> set : collection) {
if (!set.isEmpty()) {
Iterator<Integer> it = set.iterator();
int first = groups.find(it.next());
while (it.hasNext()) {
groups.union(first, it.next());
}
}
}
return groups.getGroups();
}
}