0

I want to write a method that uses the standard for loop to iterate through a given set of sets, and returns a hashmap that the disjoint sets are added to. I'm aware that the does not work correctly, it's an example of how I've tried to solve this. How do I check the elements within the sets, also without the algorithm becoming too inefficient?

public <E> Map<Set<E>, Set<Set<E>>> disjointSets(Set<Set<E>> Sets) {
    Map<Set<E>, Set<Set<E>>> result = new HashMap<>();

    for (Set<E> x : Sets) {
        for (Set<E> y : Sets) {
            if (!x.equals(y)) {
                result.put(x, Sets);
            }
        }
    }
    return result;
}
/**
 * As an example, if input sets would be:
 * [0]
 * [0, 4, 5]
 * [1, 2]
 * -> expected output should be:
 * [0] : [ [1, 2] ]
 * [0, 4, 5] : [ [1, 2] ]
 * [1, 2] : [ [0] [0, 4, 5] ]
 */
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
bells
  • 11
  • 4
  • feel free to say if something needs to be clarified – bells Oct 10 '22 at 20:41
  • Please do clarify what you are trying to achieve, example input helps. The value of x will always equals a y (when x==y itself) so you get same outcome by removing the inner for and if statements, and get a map containing a key for every member of Sets, and every value is Sets. – DuncG Oct 10 '22 at 21:04
  • @DuncG For example, if the input Sets are: ' [0] [0, 4, 5] [1, 2] ' The method output should be: ' [0] : [ [1, 2] ], [0, 4, 5] : [ [1, 2] ], [1, 2] : [ [0] [0, 4, 5] ] ' where the each key is a set checked, and the value for each key is the sets disjoint from the key set. I'm still trying to figure out HashMap, so I know my code is far from the correct way to achieve this. – bells Oct 10 '22 at 21:23
  • @AlexanderIvanchenko I think there is a misunderstanding here. I know the definition of "disjoint". In the output example, I have used commas to separate each key & their value. I understand that was a poor way to display that. So in my example for set `[1, 2]` the disjoint sets are `[0], [0, 4, 5]`. The ":" separates a key from it's own value. I hope this clarifies everything. – bells Oct 10 '22 at 22:24

2 Answers2

0

How do I check the elements within the sets

You can just cycle trough them and use Set.contains

for (Set<E> x : Sets) {
    for (Set<E> y : Sets) {
        boolean isDisjoint = true;
        for (E ey : y) {
            if (x.contains(ey)) {
                isDisjoint = false;
                break;
            }
        }
        ...
Loris Securo
  • 7,538
  • 2
  • 17
  • 28
  • Thanks! But what if I don't want to use the boolean? Can I just leave it out and make it work like that? – bells Oct 10 '22 at 22:42
  • Update: that works! Now I have the compared sets added to the result Map as keys, but each keys value has to be a set of the other sets that are disjoint. I tried to put this condition: `if (!x.contains(ey)) { result.put(x, y); }` but it gives me an error for the y, because there has to be a Set> placed there. How do I add all of the disjoint sets to the keys value? – bells Oct 10 '22 at 22:53
  • @bells check [Map.computeIfAbsent](https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/Map.html#computeIfAbsent(K,java.util.function.Function)) – Loris Securo Oct 10 '22 at 23:03
  • What do I do if the key set does not have any disjoint sets? I want the key value to be empty, like this '[ ]' – bells Oct 12 '22 at 17:36
0

You can generate a map of type Map<E,Set<Set<E>>> which associates each distinct element which might be found in these Sets with a group of Sets to which it belongs. This approach would allow to avoid redundant performing redundant iterations.

A disjoint Set that corresponds to each Set can be found in the following steps:

  • For each Set create a copy of the given Sets (that would be a value that corresponds to a particular set in the resulting map);

  • Iterate over the elements of a current Set and remove a value (denoted as disjoint in the code below) of all Sets to which a particular element belongs. A previously generated Map containing Sets associated with each distinct element would be handy for that.

In the code below, I've used Java 8 method computeIfAbsent(), which is concise and expressive (an alternative option provided in the comments):

public static <E> Map<Set<E>, Set<Set<E>>> disjointSets(Set<Set<E>> sets) {

    Map<E, Set<Set<E>>> containsElement = new HashMap<>();
    
    for (Set<E> set: sets) {
        for (E next: set) {
            containsElement   // alternatively you can use: containsElement.putIfAbsent() + containsElement.get()add()
                .computeIfAbsent(next, k -> new HashSet<>())
                .add(set);
        }
    }
    
    Map<Set<E>, Set<Set<E>>> result = new HashMap<>();
    
    for (Set<E> set: sets) {
        Set<Set<E>> disjoint = new HashSet<>(sets);
        result.put(Collections.unmodifiableSet(set), disjoint);
        
        for (E next: set) {
            disjoint.removeAll(containsElement.get(next));
        }
    }
    return result;
}

main()

public static void main(String[] args) {
    Set<Set<Integer>> sets = Set.of(
        Set.of(0), Set.of(0, 4, 5), Set.of(1, 2)
    );
    
    disjointSets(sets).forEach((element, disjoint) -> System.out.println(element + " -> " + disjoint));
}

Output:

[0] -> [[1, 2]]
[1, 2] -> [[0], [0, 5, 4]]
[0, 5, 4] -> [[1, 2]]

Time Complexity: O(n*m) (considering that we are given n sets containing m elements).

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • Thank you for your effort. I would prefer not creating any copies of the given sets, they have to be referred to. – bells Oct 11 '22 at 16:06
  • @bells What you're talking about is inherently **impossible** - every value should be represented with a separate Set of Sets (otherwise they would all be identical, which makes no sense). And I guess have a misconception regarding what copy-constructor of any Collection does. `new Set<>(sets)` creates a so-called ***shallow copy***, i.e. none of the nested Sets would be actually copied, but instead references to them would be placed into a newly created Set of Set. Is it clear? – Alexander Ivanchenko Oct 11 '22 at 16:19
  • Yes. What is the time complexity for this algorithm? – bells Oct 11 '22 at 17:12
  • @bells Time complexity of this solution **O(n*m)** (considering that we are given `n` sets containing `m` elements), which is the best possible in this case. – Alexander Ivanchenko Oct 11 '22 at 18:10