Obtaining a powerset of a set in Java

后端 未结 26 2102
青春惊慌失措
青春惊慌失措 2020-11-22 11:33

The powerset of {1, 2, 3} is:

{{}, {2}, {3}, {2, 3}, {1, 2}, {1, 3}, {1, 2, 3}, {1}}

Let\'s say I have a Set in Java:<

26条回答
  •  时光取名叫无心
    2020-11-22 11:51

    I recently had to use something like this, but needed the smallest sublists (with 1 element, then 2 elements, ...) first. I did not want to include the empty nor the whole list. Also, I did not need a list of all the sublists returned, I just needed to do some stuff with each.

    Wanted to do this without recursion, and came up with the following (with the "doing stuff" abstracted into a functional interface):

    @FunctionalInterface interface ListHandler {
        void handle(List list);
    }
    
    
    public static  void forAllSubLists(final List list, ListHandler handler) {
        int     ll = list.size();   // Length of original list
        int     ci[] = new int[ll]; // Array for list indices
        List sub = new ArrayList<>(ll);  // The sublist
        List uml = Collections.unmodifiableList(sub);    // For passing to handler
    
        for (int gl = 1, gm; gl <= ll; gl++) {  // Subgroup length 1 .. n-1
            gm = 0; ci[0] = -1; sub.add(null);  // Some inits, and ensure sublist is at least gl items long
    
            do {
                    ci[gm]++;                       // Get the next item for this member
    
                    if (ci[gm] > ll - gl + gm) {    // Exhausted all possibilities for this position
                            gm--; continue;         // Continue with the next value for the previous member
                    }
    
                    sub.set(gm, list.get(ci[gm]));  // Set the corresponding member in the sublist
    
                    if (gm == gl - 1) {             // Ok, a sublist with length gl
                            handler.handle(uml);    // Handle it
                    } else {
                            ci[gm + 1] = ci[gm];    // Starting value for next member is this 
                            gm++;                   // Continue with the next member
                    }
            } while (gm >= 0);  // Finished cycling through all possibilities
        }   // Next subgroup length
    }
    

    In this way, it's also easy to limit it to sublists of specific lengths.

提交回复
热议问题