Obtaining a powerset of a set in Java - java

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:
Set<Integer> mySet = new HashSet<Integer>();
mySet.add(1);
mySet.add(2);
mySet.add(3);
Set<Set<Integer>> powerSet = getPowerset(mySet);
How do I write the function getPowerset, with the best possible order of complexity?
(I think it might be O(2^n).)

Yes, it is O(2^n) indeed, since you need to generate, well, 2^n possible combinations. Here's a working implementation, using generics and sets:
public static <T> Set<Set<T>> powerSet(Set<T> originalSet) {
Set<Set<T>> sets = new HashSet<Set<T>>();
if (originalSet.isEmpty()) {
sets.add(new HashSet<T>());
return sets;
}
List<T> list = new ArrayList<T>(originalSet);
T head = list.get(0);
Set<T> rest = new HashSet<T>(list.subList(1, list.size()));
for (Set<T> set : powerSet(rest)) {
Set<T> newSet = new HashSet<T>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
return sets;
}
And a test, given your example input:
Set<Integer> mySet = new HashSet<Integer>();
mySet.add(1);
mySet.add(2);
mySet.add(3);
for (Set<Integer> s : SetUtils.powerSet(mySet)) {
System.out.println(s);
}

Actually, I've written code that does what you're asking for in O(1). The question is what you plan to do with the Set next. If you're just going to call size() on it, that's O(1), but if you're going to iterate it that's obviously O(2^n).
contains() would be O(n), etc.
Do you really need this?
EDIT:
This code is now available in Guava, exposed through the method Sets.powerSet(set).

Here's a solution where I use a generator, the advantage being, the entire power set is never stored at once... So you can iterate over it one-by-one without needing it to be stored in memory. I'd like to think it's a better option... Note the complexity is the same, O(2^n), but the memory requirements are reduced (assuming the garbage collector behaves! ;) )
/**
*
*/
package org.mechaevil.util.Algorithms;
import java.util.BitSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
/**
* #author st0le
*
*/
public class PowerSet<E> implements Iterator<Set<E>>,Iterable<Set<E>>{
private E[] arr = null;
private BitSet bset = null;
#SuppressWarnings("unchecked")
public PowerSet(Set<E> set)
{
arr = (E[])set.toArray();
bset = new BitSet(arr.length + 1);
}
#Override
public boolean hasNext() {
return !bset.get(arr.length);
}
#Override
public Set<E> next() {
Set<E> returnSet = new TreeSet<E>();
for(int i = 0; i < arr.length; i++)
{
if(bset.get(i))
returnSet.add(arr[i]);
}
//increment bset
for(int i = 0; i < bset.size(); i++)
{
if(!bset.get(i))
{
bset.set(i);
break;
}else
bset.clear(i);
}
return returnSet;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not Supported!");
}
#Override
public Iterator<Set<E>> iterator() {
return this;
}
}
To call it, use this pattern:
Set<Character> set = new TreeSet<Character> ();
for(int i = 0; i < 5; i++)
set.add((char) (i + 'A'));
PowerSet<Character> pset = new PowerSet<Character>(set);
for(Set<Character> s:pset)
{
System.out.println(s);
}
It's from my Project Euler Library... :)

If n < 63, which is a reasonable assumption since you'd run out of memory (unless using an iterator implementation) trying to construct the power set anyway, this is a more concise way to do it. Binary operations are way faster than Math.pow() and arrays for masks, but somehow Java users are afraid of them...
List<T> list = new ArrayList<T>(originalSet);
int n = list.size();
Set<Set<T>> powerSet = new HashSet<Set<T>>();
for( long i = 0; i < (1 << n); i++) {
Set<T> element = new HashSet<T>();
for( int j = 0; j < n; j++ )
if( (i >> j) % 2 == 1 ) element.add(list.get(j));
powerSet.add(element);
}
return powerSet;

Here is a tutorial describing exactly what you want, including the code. You're correct in that the complexity is O(2^n).

I came up with another solution based on #Harry He's ideas. Probably not the most elegant but here it goes as I understand it:
Let's take the classical simple example PowerSet of S P(S) = {{1},{2},{3}}.
We know the formula to get the number of subsets is 2^n (7 + empty set).
For this example 2^3 = 8 subsets.
In order to find each subset we need to convert 0-7 decimal to binary representation shown in the conversion table below:
If we traverse the table row by row, each row will result in a subset and the values of each subset will come from the enabled bits.
Each column in the Bin Value section corresponds to the index position in the original input Set.
Here my code:
public class PowerSet {
/**
* #param args
*/
public static void main(String[] args) {
PowerSet ps = new PowerSet();
Set<Integer> set = new HashSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
for (Set<Integer> s : ps.powerSet(set)) {
System.out.println(s);
}
}
public Set<Set<Integer>> powerSet(Set<Integer> originalSet) {
// Original set size e.g. 3
int size = originalSet.size();
// Number of subsets 2^n, e.g 2^3 = 8
int numberOfSubSets = (int) Math.pow(2, size);
Set<Set<Integer>> sets = new HashSet<Set<Integer>>();
ArrayList<Integer> originalList = new ArrayList<Integer>(originalSet);
for (int i = 0; i < numberOfSubSets; i++) {
// Get binary representation of this index e.g. 010 = 2 for n = 3
String bin = getPaddedBinString(i, size);
//Get sub-set
Set<Integer> set = getSet(bin, originalList));
sets.add(set);
}
return sets;
}
//Gets a sub-set based on the binary representation. E.g. for 010 where n = 3 it will bring a new Set with value 2
private Set<Integer> getSet(String bin, List<Integer> origValues){
Set<Integer> result = new HashSet<Integer>();
for(int i = bin.length()-1; i >= 0; i--){
//Only get sub-sets where bool flag is on
if(bin.charAt(i) == '1'){
int val = origValues.get(i);
result.add(val);
}
}
return result;
}
//Converts an int to Bin and adds left padding to zero's based on size
private String getPaddedBinString(int i, int size) {
String bin = Integer.toBinaryString(i);
bin = String.format("%0" + size + "d", Integer.parseInt(bin));
return bin;
}
}

If you're using Eclipse Collections (formerly GS Collections), you can use the powerSet() method on all SetIterables.
MutableSet<Integer> set = UnifiedSet.newSetWith(1, 2, 3);
System.out.println("powerSet = " + set.powerSet());
// prints: powerSet = [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
Note: I am a committer for Eclipse Collections.

I was looking for a solution that wasn't as huge as the ones posted here. This targets Java 7, so it will require a handful of pastes for versions 5 and 6.
Set<Set<Object>> powerSetofNodes(Set<Object> orig) {
Set<Set<Object>> powerSet = new HashSet<>(),
runSet = new HashSet<>(),
thisSet = new HashSet<>();
while (powerSet.size() < (Math.pow(2, orig.size())-1)) {
if (powerSet.isEmpty()) {
for (Object o : orig) {
Set<Object> s = new TreeSet<>();
s.add(o);
runSet.add(s);
powerSet.add(s);
}
continue;
}
for (Object o : orig) {
for (Set<Object> s : runSet) {
Set<Object> s2 = new TreeSet<>();
s2.addAll(s);
s2.add(o);
powerSet.add(s2);
thisSet.add(s2);
}
}
runSet.clear();
runSet.addAll(thisSet);
thisSet.clear();
}
powerSet.add(new TreeSet());
return powerSet;
Here's some example code to test:
Set<Object> hs = new HashSet<>();
hs.add(1);
hs.add(2);
hs.add(3);
hs.add(4);
for(Set<Object> s : powerSetofNodes(hs)) {
System.out.println(Arrays.toString(s.toArray()));
}

Here is an easy iterative O(2^n) solution:
public static Set<Set<Integer>> powerSet(List<Integer> intList){
Set<Set<Integer>> result = new HashSet();
result.add(new HashSet());
for (Integer i : intList){
Set<Set<Integer>> temp = new HashSet();
for(Set<Integer> intSet : result){
intSet = new HashSet(intSet);
intSet.add(i);
temp.add(intSet);
}
result.addAll(temp);
}
return result;
}

Some of the solutions above suffer when the size of the set is large because they are creating a lot of object garbage to be collected and require copying data. How can we avoid that? We can take advantage of the fact that we know how big the result set size will be (2^n), preallocate an array that big, and just append to the end of it, never copying.
The speedup grows quickly with n. I compared it to João Silva's solution above. On my machine (all measurements approximate), n=13 is 5x faster, n=14 is 7x, n=15 is 12x, n=16 is 25x, n=17 is 75x, n=18 is 140x. So that garbage creation/collection and copying is dominating in what otherwise seem to be similar big-O solutions.
Preallocating the array at the beginning appears to be a win compared to letting it grow dynamically. With n=18, dynamic growing takes about twice as long overall.
public static <T> List<List<T>> powerSet(List<T> originalSet) {
// result size will be 2^n, where n=size(originalset)
// good to initialize the array size to avoid dynamic growing
int resultSize = (int) Math.pow(2, originalSet.size());
// resultPowerSet is what we will return
List<List<T>> resultPowerSet = new ArrayList<List<T>>(resultSize);
// Initialize result with the empty set, which powersets contain by definition
resultPowerSet.add(new ArrayList<T>(0));
// for every item in the original list
for (T itemFromOriginalSet : originalSet) {
// iterate through the existing powerset result
// loop through subset and append to the resultPowerset as we go
// must remember size at the beginning, before we append new elements
int startingResultSize = resultPowerSet.size();
for (int i=0; i<startingResultSize; i++) {
// start with an existing element of the powerset
List<T> oldSubset = resultPowerSet.get(i);
// create a new element by adding a new item from the original list
List<T> newSubset = new ArrayList<T>(oldSubset);
newSubset.add(itemFromOriginalSet);
// add this element to the result powerset (past startingResultSize)
resultPowerSet.add(newSubset);
}
}
return resultPowerSet;
}

The following solution is borrowed from my book "Coding Interviews: Questions, Analysis & Solutions":
Some integers in an array are selected that compose a combination. A set of bits is utilized, where each bit stands for an integer in the array. If the i-th character is selected for a combination, the i-th bit is 1; otherwise, it is 0. For instance, three bits are used for combinations of the array [1, 2, 3]. If the first two integers 1 and 2 are selected to compose a combination [1, 2], the corresponding bits are {1, 1, 0}. Similarly, bits corresponding to another combination [1, 3] are {1, 0, 1}. We are able to get all combinations of an array with length n if we can get all possible combinations of n bits.
A number is composed of a set of bits. All possible combinations of n bits correspond to numbers
from 1 to 2^n-1. Therefore, each number in the range between 1 and 2^n-1 corresponds to a combination of an array with length n. For example, the number 6 is composed of bits {1, 1, 0}, so the first and second characters are selected in the array [1, 2, 3] to generate the combination [1, 2]. Similarly, the number 5 with bits {1, 0, 1} corresponds to the combination [1, 3].
The Java code to implement this solution looks like below:
public static ArrayList<ArrayList<Integer>> powerSet(int[] numbers) {
ArrayList<ArrayList<Integer>> combinations = new ArrayList<ArrayList<Integer>>();
BitSet bits = new BitSet(numbers.length);
do{
combinations.add(getCombination(numbers, bits));
}while(increment(bits, numbers.length));
return combinations;
}
private static boolean increment(BitSet bits, int length) {
int index = length - 1;
while(index >= 0 && bits.get(index)) {
bits.clear(index);
--index;
}
if(index < 0)
return false;
bits.set(index);
return true;
}
private static ArrayList<Integer> getCombination(int[] numbers, BitSet bits){
ArrayList<Integer> combination = new ArrayList<Integer>();
for(int i = 0; i < numbers.length; ++i) {
if(bits.get(i))
combination.add(numbers[i]);
}
return combination;
}
The method increment increases a number represented in a set of bits. The algorithm clears 1 bits
from the rightmost bit until a 0 bit is found. It then sets the rightmost 0 bit to 1. For example, in order to increase the number 5 with bits {1, 0, 1}, it clears 1 bits from the right side and sets the rightmost 0 bit to 1. The bits become {1, 1, 0} for the number 6, which is the result of increasing 5 by 1.

import java.util.Set;
import com.google.common.collect.*;
Set<Set<Integer>> sets = Sets.powerSet(ImmutableSet.of(1, 2, 3));

If S is a finite set with N elements, then the power set of S contains 2^N elements. The time to simply enumerate the elements of the powerset is 2^N, so O(2^N) is a lower bound on the time complexity of (eagerly) constructing the powerset.
Put simply, any computation that involves creating powersets is not going to scale for large values of N. No clever algorithm will help you ... apart from avoiding the need to create the powersets!

One way without recursion is the following: Use a binary mask and make all the possible combinations.
public HashSet<HashSet> createPowerSet(Object[] array)
{
HashSet<HashSet> powerSet=new HashSet();
boolean[] mask= new boolean[array.length];
for(int i=0;i<Math.pow(2, array.length);i++)
{
HashSet set=new HashSet();
for(int j=0;j<mask.length;j++)
{
if(mask[i])
set.add(array[j]);
}
powerSet.add(set);
increaseMask(mask);
}
return powerSet;
}
public void increaseMask(boolean[] mask)
{
boolean carry=false;
if(mask[0])
{
mask[0]=false;
carry=true;
}
else
mask[0]=true;
for(int i=1;i<mask.length;i++)
{
if(mask[i]==true && carry==true)
mask[i]=false;
else if (mask[i]==false && carry==true)
{
mask[i]=true;
carry=false;
}
else
break;
}
}

Algorithm:
Input: Set[], set_size
1. Get the size of power set
powet_set_size = pow(2, set_size)
2 Loop for counter from 0 to pow_set_size
(a) Loop for i = 0 to set_size
(i) If ith bit in counter is set
Print ith element from set for this subset
(b) Print seperator for subsets i.e., newline
#include <stdio.h>
#include <math.h>
void printPowerSet(char *set, int set_size)
{
/*set_size of power set of a set with set_size
n is (2**n -1)*/
unsigned int pow_set_size = pow(2, set_size);
int counter, j;
/*Run from counter 000..0 to 111..1*/
for(counter = 0; counter < pow_set_size; counter++)
{
for(j = 0; j < set_size; j++)
{
/* Check if jth bit in the counter is set
If set then pront jth element from set */
if(counter & (1<<j))
printf("%c", set[j]);
}
printf("\n");
}
}
/*Driver program to test printPowerSet*/
int main()
{
char set[] = {'a','b','c'};
printPowerSet(set, 3);
getchar();
return 0;
}

This is my recursive solution which can get the power set of any set using Java Generics. Its main idea is to combine the head of the input array with all the possible solutions of the rest of the array as follows.
import java.util.LinkedHashSet;
import java.util.Set;
public class SetUtil {
private static<T> Set<Set<T>> combine(T head, Set<Set<T>> set) {
Set<Set<T>> all = new LinkedHashSet<>();
for (Set<T> currentSet : set) {
Set<T> outputSet = new LinkedHashSet<>();
outputSet.add(head);
outputSet.addAll(currentSet);
all.add(outputSet);
}
all.addAll(set);
return all;
}
//Assuming that T[] is an array with no repeated elements ...
public static<T> Set<Set<T>> powerSet(T[] input) {
if (input.length == 0) {
Set <Set<T>>emptySet = new LinkedHashSet<>();
emptySet.add(new LinkedHashSet<T>());
return emptySet;
}
T head = input[0];
T[] newInputSet = (T[]) new Object[input.length - 1];
for (int i = 1; i < input.length; ++i) {
newInputSet[i - 1] = input[i];
}
Set<Set<T>> all = combine(head, powerSet(newInputSet));
return all;
}
public static void main(String[] args) {
Set<Set<Integer>> set = SetUtil.powerSet(new Integer[] {1, 2, 3, 4, 5, 6});
System.out.println(set);
}
}
This will output:
[[1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5], [1, 2, 3, 4, 6], [1, 2, 3, 4], [1, 2, 3, 5, 6], [1, 2, 3, 5], [1, 2, 3, 6], [1, 2, 3], [1, 2, 4, 5, 6], [1, 2, 4, 5], [1, 2, 4, 6], [1, 2, 4], [1, 2, 5, 6], [1, 2, 5], [1, 2, 6], [1, 2], [1, 3, 4, 5, 6], [1, 3, 4, 5], [1, 3, 4, 6], [1, 3, 4], [1, 3, 5, 6], [1, 3, 5], [1, 3, 6], [1, 3], [1, 4, 5, 6], [1, 4, 5], [1, 4, 6], [1, 4], [1, 5, 6], [1, 5], [1, 6], [1], [2, 3, 4, 5, 6], [2, 3, 4, 5], [2, 3, 4, 6], [2, 3, 4], [2, 3, 5, 6], [2, 3, 5], [2, 3, 6], [2, 3], [2, 4, 5, 6], [2, 4, 5], [2, 4, 6], [2, 4], [2, 5, 6], [2, 5], [2, 6], [2], [3, 4, 5, 6], [3, 4, 5], [3, 4, 6], [3, 4], [3, 5, 6], [3, 5], [3, 6], [3], [4, 5, 6], [4, 5], [4, 6], [4], [5, 6], [5], [6], []]

Another sample implementation:
public static void main(String args[])
{
int[] arr = new int[]{1,2,3,4};
// Assuming that number of sets are in integer range
int totalSets = (int)Math.pow(2,arr.length);
for(int i=0;i<totalSets;i++)
{
String binaryRep = Integer.toBinaryString(i);
for(int j=0;j<binaryRep.length();j++)
{
int index=binaryRep.length()-1-j;
if(binaryRep.charAt(index)=='1')
System.out.print(arr[j] +" ");
}
System.out.println();
}
}

This is my approach with lambdas.
public static <T> Set<Set<T>> powerSet(T[] set) {
return IntStream
.range(0, (int) Math.pow(2, set.length))
.parallel() //performance improvement
.mapToObj(e -> IntStream.range(0, set.length).filter(i -> (e & (0b1 << i)) != 0).mapToObj(i -> set[i]).collect(Collectors.toSet()))
.map(Function.identity())
.collect(Collectors.toSet());
}
Or in parallel (see parallel() comment):
Size of input set: 18
Logical processors: 8 à 3.4GHz
Performance improvement: 30%

// input: S
// output: P
// S = [1,2]
// P = [], [1], [2], [1,2]
public static void main(String[] args) {
String input = args[0];
String[] S = input.split(",");
String[] P = getPowerSet(S);
if (P.length == Math.pow(2, S.length)) {
for (String s : P) {
System.out.print("[" + s + "],");
}
} else {
System.out.println("Results are incorrect");
}
}
private static String[] getPowerSet(String[] s) {
if (s.length == 1) {
return new String[] { "", s[0] };
} else {
String[] subP1 = getPowerSet(Arrays.copyOfRange(s, 1, s.length));
String[] subP2 = new String[subP1.length];
for (int i = 0; i < subP1.length; i++) {
subP2[i] = s[0] + subP1[i];
}
String[] P = new String[subP1.length + subP2.length];
System.arraycopy(subP1, 0, P, 0, subP1.length);
System.arraycopy(subP2, 0, P, subP1.length, subP2.length);
return P;
}
}

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<T> {
void handle(List<T> list);
}
public static <T> void forAllSubLists(final List<T> list, ListHandler handler) {
int ll = list.size(); // Length of original list
int ci[] = new int[ll]; // Array for list indices
List<T> sub = new ArrayList<>(ll); // The sublist
List<T> 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.

public class PowerSet {
public static List<HashSet<Integer>> powerset(int[] a) {
LinkedList<HashSet<Integer>> sets = new LinkedList<HashSet<Integer>>();
int n = a.length;
for (int i = 0; i < 1 << n; i++) {
HashSet<Integer> set = new HashSet<Integer>();
for (int j = 0; j < n; j++) {
if ((1 << j & i) > 0)
set.add(a[j]);
}
sets.add(set);
}
return sets;
}
public static void main(String[] args) {
List<HashSet<Integer>> sets = PowerSet.powerset(new int[]{ 1, 2, 3 });
for (HashSet<Integer> set : sets) {
for (int i : set)
System.out.print(i);
System.out.println();
}
}
}

Yet another solution - with java8+ streaming api
It is lazy and ordered so it returns correct subsets when it is used with "limit()".
public long bitRangeMin(int size, int bitCount){
BitSet bs = new BitSet(size);
bs.set(0, bitCount);
return bs.toLongArray()[0];
}
public long bitRangeMax(int size, int bitCount){
BitSet bs = BitSet.valueOf(new long[]{0});
bs.set(size - bitCount, size);
return bs.toLongArray()[0];
}
public <T> Stream<List<T>> powerSet(Collection<T> data)
{
List<T> list = new LinkedHashSet<>(data).stream().collect(Collectors.toList());
Stream<BitSet> head = LongStream.of(0).mapToObj( i -> BitSet.valueOf(new long[]{i}));
Stream<BitSet> tail = IntStream.rangeClosed(1, list.size())
.boxed()
.flatMap( v1 -> LongStream.rangeClosed( bitRangeMin(list.size(), v1), bitRangeMax(list.size(), v1))
.mapToObj(v2 -> BitSet.valueOf(new long[]{v2}))
.filter( bs -> bs.cardinality() == v1));
return Stream.concat(head, tail)
.map( bs -> bs
.stream()
.mapToObj(list::get)
.collect(Collectors.toList()));
}
And the client code is
#Test
public void testPowerSetOfGivenCollection(){
List<Character> data = new LinkedList<>();
for(char i = 'a'; i < 'a'+5; i++ ){
data.add(i);
}
powerSet(data)
.limit(9)
.forEach(System.out::print);
}
/* Prints : [][a][b][c][d][e][a, b][a, c][b, c] */

We could write the power set with or without using recursion. Here is an attempt without recursion:
public List<List<Integer>> getPowerSet(List<Integer> set) {
List<List<Integer>> powerSet = new ArrayList<List<Integer>>();
int max = 1 << set.size();
for(int i=0; i < max; i++) {
List<Integer> subSet = getSubSet(i, set);
powerSet.add(subSet);
}
return powerSet;
}
private List<Integer> getSubSet(int p, List<Integer> set) {
List<Integer> subSet = new ArrayList<Integer>();
int position = 0;
for(int i=p; i > 0; i >>= 1) {
if((i & 1) == 1) {
subSet.add(set.get(position));
}
position++;
}
return subSet;
}

A sub-set of t is any set that can be made by removing zero or more elements of t. The withoutFirst subset adds the subsets of t that are missing the first element and the for loop will deal with adding subsets with the first element. For example, if t contained the elements ["1", "2", "3"], missingFirst will add [[""],
["2"], ["3"], ["2","3"]] and the for loop will stick the "1" in front of these element and add it to the newSet. So we'll end up with [[""], ["1"], ["2"], ["3"], ["1", "2"], ["1", "3"], ["2","3"], ["1", "2", "3"]].
public static Set<Set<String>> allSubsets(Set<String> t) {
Set<Set<String>> powerSet = new TreeSet<>();
if(t.isEmpty()) {
powerSet.add(new TreeSet<>());
return powerSet;
}
String first = t.get(0);
Set<Set<String>> withoutFirst = allSubsets(t.subSet(1, t.size()));
for (List<String> 1st : withoutFirst) {
Set<String> newSet = new TreeSet<>();
newSet.add(first);
newSet.addAll(lst);
powerSet.add(newSet);
}
powerSet.addAll(withoutFirst);
return powerSet;
}

Here is to generate a power set. The idea is first = S[0] and smaller sets be S[1,...n].
Compute all subsets of smallerSet and put them in allsubsets.
For each subsets in allsubsets, clone it and add first to the subset.
ArrayList<ArrayList<Integer>> getSubsets(ArrayList<Integer> set, int index){
ArrayList<ArrayList<Integer>> allsubsets;
if(set.size() == index){
allsubsets = new ArrayList<ArrayList<Integer>>();
allsubsets.add(new ArrayList<Integer>()); // the empty set
}else{
allsubsets = getSubsets(set, index+1);
int item = set.get(index);
ArrayList<ArrayList<Integer>> moresubsets = new ArrayList<ArrayList<Integer>>();
for(ArrayList<Integer> subset: allsubsets){
ArrayList<Integer> newsubset = new ArrayList<Integer>();
newsubset.addAll(subset);
newsubset.add(item);
moresubsets.add(newsubset);
}
moresubsets.addAll(moresubsets);
}
return allsubsets;
}

package problems;
import java.util.ArrayList;
import java.util.List;
public class SubsetFinderRecursive {
public static void main(String[] args) {
//input
int[] input = new int[3];
for(int i=0; i<input.length; i++) {
input[i] = i+1;
}
// root node of the tree
Node root = new Node();
// insert values into tree
for(int i=0; i<input.length; i++) {
insertIntoTree(root, input[i]);
}
// print leaf nodes for subsets
printLeafNodes(root);
}
static void printLeafNodes(Node root) {
if(root == null) {
return;
}
// Its a leaf node
if(root.left == null && root.right == null) {
System.out.println(root.values);
return;
}
// if we are not at a leaf node, then explore left and right
if(root.left !=null) {
printLeafNodes(root.left);
}
if(root.right != null) {
printLeafNodes(root.right);
}
}
static void insertIntoTree(Node root, int value) {
// Error handling
if(root == null) {
return;
}
// if there is a sub tree then go down
if(root.left !=null && root.right != null) {
insertIntoTree(root.left, value);
insertIntoTree(root.right, value);
}
// if we are at the leaf node, then we have 2 choices
// Either exclude or include
if(root.left == null && root.right == null) {
// exclude
root.left = new Node();
root.left.values.addAll(root.values);
// include
root.right = new Node();
root.right.values.addAll(root.values);
root.right.values.add(value);
return;
}
}
}
class Node {
Node left;
Node right;
List<Integer> values = new ArrayList<Integer>();
}

This function solved this problem by recursion but make variable named powerset as a Global Variable:
static ArrayList<ArrayList<Integer>> powerSet = new ArrayList<>();
public static void getPowerSet(Queue<Integer> a) {
int n = a.poll();
if (!a.isEmpty()) {
getPowerSet(a);
}
int s = powerSet.size();
for (int i = 0; i < s; i++) {
ArrayList<Integer> ne = new ArrayList<>();
for (int j = 0; j < powerSet.get(i).size(); j++) {
ne.add(powerSet.get(i).get(j));
}
ne.add(n);
powerSet.add(ne);
}
ArrayList<Integer> p = new ArrayList<>();
p.add(n);
powerSet.add(p);
}

Related

Reverse subset of ArrayList using multidimensional ArrayList in Java

I am trying to reverse a sublist in a List using the indices provided in a multidimensional List.
I don't have much experience using multidimensional lists/arrays. I don't understand why this doesn't work.
/*
Given a List<Integer> list and List<List<Integer>> operations
reverse the sublist and print out the list after all the operations have been done.
Ex: [5, 3, 2, 1, 3]
[[0,1], [1, 3]]
*/
import java.util.*;
public class ReverseParameters {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> operations = new ArrayList<>(2);
for(int i= 0; i < 3; i++){
operations.add(new ArrayList<>());
}
operations.get(0).add(1);
operations.get(1).add(3);
subList(list, operations);
}
public static void subList (List<Integer> list, List<List<Integer>> operations) {
System.out.println(list);
int vertCount = operations.size();
for (int i = 0; i < vertCount; i++) {
int edgeCount = operations.get(i).size();
for (int j = 0; j < edgeCount; j++) {
int startInd = i;
int endInd = operations.get(i).get(j);
int shift = endInd - startInd;
int right = Math.min(i + shift - 1, list.size() - 1);
int temp = 0;
while (startInd < right) {
temp = list.get(startInd);
list.set(startInd, list.get(right));
list.set(right, temp);
startInd+=1;
right-=1;
}
System.out.println();
System.out.printf(" %d %d%n", startInd, endInd);
System.out.println();
}
}
System.out.println(list);
}
}
The output of this code using [[0,1], [1, 3]] as the indecies is:
[5, 2, 3, 1, 3]
but it should be:
[3, 1, 2, 5, 3]
Can someone please help point me in the right direction?
This can be done as simple as this.
public class Main
{
public static void main(String[] args)
{
//Given a List<Integer> list and List<List<Integer>> operations
//reverse the sublist and print out the list after all the operations have been done.
//Ex: [5, 3, 2, 1, 3]
// [[0,1], [1, 3]]
//Target: [3, 1, 2, 5, 3]
//Steps:
// 0 1 2 3 4 (Indices)
//###############
//[5, 3, 2, 1, 3]
//[3, 5, 2, 1, 3] // Swap index of 0 and 1.
//[3, 1, 2, 5, 3] // Swap index of 1 and 3.
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> listOfList = new ArrayList<List<Integer>>(2);
listOfList.add(Arrays.asList(0, 1));
listOfList.add(Arrays.asList(1, 3));
for(int i=0; i < listOfList.size(); ++i) {
final int indexA = listOfList.get(i).get(0); //[0 , [1
final int indexB = listOfList.get(i).get(1); // 1], 3]
//Swap the indices.
final int tmpValue = list.get(indexA);
list.set(indexA, list.get(indexB));
list.set(indexB, tmpValue);
}
System.out.println(list);
//[3, 1, 2, 5, 3]
}
}
You are overcomplicating your code with unnecessary variables that makes it difficult to find the problem. Please se a more simple code with explanation:
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> operations = new ArrayList<>(2);
// Initialize your operations
operations.add(Arrays.asList(0,1));
operations.add(Arrays.asList(1,3));
subList(list, operations);
}
public static void subList (List<Integer> list, List<List<Integer>> operations) {
// You just iterate over the operations
for (List<Integer> operation : operations) {
// For each operation, store left and right indexes.
int left = operation.get(0);
int right = operation.get(1);
// Iterate until both indexes find each other
while (left < right) {
// Swap left and right elements in input list
int aux = list.get(left);
list.set(left, list.get(right));
list.set(right, aux);
// Now you move your indexes
++left;
--right;
}
}
System.out.println(list);
}
Please note that, depending on what the question asks, you may also need to verify if the operations indexes are within the list boundaries so you won't end up getting an ArrayIndexOutOfBoundsException. So be always careful with edge cases.
You can get subset by List.subList() , and reverse by Collections.reverse().
static void reverseSubsets(List<Integer> list, List<List<Integer>> subsets) {
for (List<Integer> subset : subsets)
Collections.reverse(list.subList(subset.get(0), subset.get(1) + 1));
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> subsets = List.of(List.of(0, 1), List.of(1, 3));
reverseSubsets(list, subsets);
System.out.println(list);
}
output:
[3, 1, 2, 5, 3]
Note:
toIndex in List.subList(int fromIndex, int toIndex) is exclusive high endpoint of the subList. So you must add 1 to subset.get(1).

How to find cartesian product of an arbitrary number of ArrayLists - Java

I'm trying to figure out how to output the cartesian product of two or more lists in a java method such that I have a List of List's as the output.
For example, if i have:
a = [1,2] , b = [3,4] , c = [5,6]
Then the output would be:
[[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6].....]
I have managed to write the code such that it works for two lists but when it becomes three or more it doesnt work. In my code, i have initially added the cartesian product of the first two lists to a larger list. And from there i tried adding the remaining elements into those such lists, but i am presented with an infinite loop for some reason.
public static List<List<Integer>> cartprod(List<Entry> entries) {
// TODO: implement this
List<List<Integer>> cartprod = new ArrayList<List<Integer>>();
Entry first = entries.get(0);
for (int i =0; i < first.getValues().size(); i++) {
int element = first.getValues().get(i);
for (int j = 1; j < entries.size(); j++) {
Entry entry = entries.get(j);
for (int k =0; k < entry.getValues().size(); k++) {
int entry_element = entry.getValues().get(k);
List<Integer> product = new ArrayList<Integer>();
product.add(element);
product.add(entry_element);
cartprod.add(product);
}
}
}
//HELP WITH THIS CODE BLOCK
// ###################################
// int entries_size = entries.size();
// for (int i=2; i< entries.size(); i++) {
// List<Integer> nextList = entries.get(i).getValues();
// for (int j=0; j< cartprod.size(); j++) {
// List<Integer> element = cartprod.get(j);
// for (int k=0; k < nextList.size(); k++) {
// System.out.println(nextList);
// List<Integer> newList = element;
// int numToAdd = nextList.get(k);
// System.out.println(numToAdd+"\n");
// newList.add(numToAdd);
// cartprod.add(newList);
// }
// }
// }
return cartprod;
}
this question sounds a lot like homework/interview question...but i'll give you a hint anyway.
you are going about it the wrong way, nested loops will not help you in this case, because you want to be able to work with any number of lists.
think of it this way: every element in the cartesian product of lists L1,L2,...Ln is made up of one element from L1, and the rest is the cartesian product of L2...Ln as such:
{L1[0] + cartesian(L2,L3,...Ln)} , {L1[1] + cartesian(L2,L3,...,Ln)} and so on up to the length of L1.
i hope you get where i'm going with this, good luck!
P.S. if this question is indeed not homework, i'll post the java code later.
P.P.S. extra points if you calculate cartesian(Lk,...,Ln) only once for each k where n > k > 1 ;)
It's a lot easier to calculate Cartesian Products using recursion. Here is a recursive code:
public List<List<Integer>> calculateCartesianProduct(List<List<Integer>> inputLists) {
List<List<Integer>> cartesianProducts = new ArrayList<>();
if (inputLists != null && inputLists.size() > 0) {
// separating the list at 0th index
List<Integer> initialList = inputLists.get(0);
// recursive call
List<List<Integer>> remainingLists = calculateCartesianProduct(inputLists.subList(1, inputLists.size()));
// calculating the cartesian product
initialList.forEach(element -> {
remainingLists.forEach(remainingList -> {
ArrayList<Integer> cartesianProduct = new ArrayList<>();
cartesianProduct.add(element);
cartesianProduct.addAll(remainingList);
cartesianProducts.add(cartesianProduct);
});
});
} else {
// Base Condition for Recursion (returning empty List as only element)
cartesianProducts.add(new ArrayList<>());
}
return cartesianProducts;
}
Here he is how I tested it:
List<Integer> a = Arrays.asList(1, 2);
List<Integer> b = Arrays.asList(3, 4);
List<Integer> c = Arrays.asList(5, 6);
List<List<Integer>> inputLists = Arrays.asList(a, b, c);
System.out.println(calculateCartesianProduct(inputLists));
Output:
[[1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]

How to sort one array based on the values of other array in Java?

I am a newbie in Java. I am trying to sort array arr[] according to the values of array val[] and it should maintain the insertion order.
int arr[] = {2,3,2,4,5,12,2,3,3,3,12};
int val[] = {3,4,3,1,1,2,3,4,4,4,2};
I am using this :
ArrayList <Integer> al = new ArrayList <Integer> () ;
for(int i = 0 ; i < arr.length ; i++)
al.add(arr);
Collections.sort(al , (left , right) -> val[al.indexOf(left)] -
val[al.indexOf(right)])
My output should be
4 5 12 12 2 2 2 3 3 3 3
Your two arrays are different lengths so this fails but if you fix that problem this should work:
static <T extends Comparable<T>> List<Integer> getSortOrder(List<T> list) {
// Ints in increasing order from 0. One for each entry in the list.
List<Integer> order = IntStream.rangeClosed(0, list.size() - 1).boxed().collect(Collectors.toList());
Collections.sort(order, (o1, o2) -> {
// Comparing the contents of the list at the position of the integer.
return list.get(o1).compareTo(list.get(o2));
});
return order;
}
// Array form.
static <T extends Comparable<T>> List<Integer> getSortOrder(T[] list) {
return getSortOrder(Arrays.asList(list));
}
static <T> List<T> reorder(List<T> list, List<Integer> order) {
return order.stream().map(i -> list.get(i)).collect(Collectors.toList());
}
// Array form.
static <T> T[] reorder(T[] list, List<Integer> order) {
return reorder(Arrays.asList(list), order).toArray(list);
}
public void test(String[] args) {
Integer arr[] = {2,3,2,4,5,12,2,3,3,3,12};
Integer val[] = {3,4,3,1,1,2,2,3,4,4,4,2};
List<Integer> sortOrder = getSortOrder(val);
Integer[] reordered = reorder(arr, sortOrder);
System.out.println(Arrays.toString(reordered));
}
The val array seems to be one element longer.
int[] arr = {2, 3, 2, 4, 5, 12, 2, 3, 3, 3, 12};
int[] val = {3, 4, 3, 1, 1, 2, 2, 3, 4, 4, /*4,*/ 2};
int[] sortedArr = IntStream.range(0, arr.length)
.mapToObj(i -> new int[] {arr[i], val[i]})
.sorted((lhs, rhs) -> Integer.compare(lhs[1], rhs[1]))
.mapToInt(pair -> pair[0])
.toArray();
System.out.println(Arrays.toString(sortedArr));
which results in
[4, 5, 12, 2, 12, 2, 2, 3, 3, 3, 3]
As sorting is stable, one could either do two sorts or combine them:
int[] sortedArr = IntStream.range(0, arr.length)
.mapToObj(i -> new int[] {arr[i], val[i]})
.sorted((lhs, rhs) -> Integer.compare(lhs[0], rhs[0]))
.sorted((lhs, rhs) -> Integer.compare(lhs[1], rhs[1]))
.mapToInt(pair -> pair[0])
.toArray();
and then, voila
[4, 5, 2, 12, 12, 2, 2, 3, 3, 3, 3]
Just write your sorting algorithm of choice, compare values from val and sort both arr and val accordingly.
Solely for the sake of brevity, here's an example using bubble-sort:
static void sortByVal(int[] arr, int[] val) {
if (arr.length != val.length) { return; }
for (int i=0; i < val.length; i++) {
for (int j=1; j < (val.length-i); j++) {
if (val[j-1] > val[j]) {
int temp = val[j-1];
val[j-1] = val[j];
val[j] = temp;
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
}
Note however that you usually shouldn't resort to reimplementing a sorting algorithm but rather switch to appropriate datastructures.
For instance instead of using a key-array and a values-array, use an array containing key-value pairs. This array can then be sorted easily:
Collections.sort(array, (p0, p1) -> Integer.compare(p0.val, p1.val));
You should look at your logic
val[0] = arr[3] = 4
val[1] = arr[4] = 5
val[2] = arr[3] the value is 4 following your current pattern.
To get 12 the desired value you would have to remove the previously used 4,5
This pattern contradicts what was done at val[1] because 4 was not removed.

Go through all permutations of an array recursively

I am trying to write a recursive function to produce all permutations of an array.
static int permus[] = new int[] { 1, 2, 3, 4, 5 };
static void testPermu(int start)
{
// Print it
System.out.println(Arrays.toString(permus));
int k;
for (int i = start + 1; i < permus.length; i++) {
// swap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
testPermu(i);
// unswap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
}
}
It's invoked as testPermu(0) and should produce all permutations, however that does not work. How can I fix it?
It needs to be recursive, each time the function is invoked, it should get a fresh permutation.
output now is
[1, 2, 3, 4, 5]
[2, 1, 3, 4, 5]
[2, 3, 1, 4, 5]
[2, 3, 4, 1, 5]
[2, 3, 4, 5, 1]
[2, 3, 5, 4, 1]
[2, 4, 3, 1, 5]
[2, 4, 3, 5, 1]
[2, 5, 3, 4, 1]
[3, 2, 1, 4, 5]
[3, 2, 4, 1, 5]
[3, 2, 4, 5, 1]
[3, 2, 5, 4, 1]
[4, 2, 3, 1, 5]
[4, 2, 3, 5, 1]
[5, 2, 3, 4, 1]
You can see that many of the permutations are missing.
I'm writing it in Java but I'll understand example in C, javascript or anything else as long as it's not using some library tricks not available in Java.
Three corrections are needed in order to work:
print only if (start == permus.length-1), otherwise you'll see duplicates
start the for loop from i = start, not i = start + 1
recursively call testPermu(start + 1); instead of testPermu(i);
Here is a full example:
package eric.math;
import java.util.Arrays;
public class Permute {
// swap 2 elements of an array,
void swap(int[] arr, int x, int y) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
/**
* print permutations of array
* #param arr
* original int array,
*/
void permute(int[] arr) {
permute(arr, 0, arr.length - 1);
}
/**
* print permutations of array
*
* #param arr
* original int array,
* #param i
* start index
* #param n
* end index
*/
void permute(int[] arr, int i, int n) {
int j;
if (i == n)
System.out.println(Arrays.toString(arr));
else {
for (j = i; j <= n; j++) {
swap(arr, i, j);
permute(arr, i + 1, n);
swap(arr, i, j); // backtrack
}
}
}
public static void main(String[] args) {
int arr[] = { 1, 2, 3 };
new Permute().permute(arr);
}
}
#Enric solution is nice, but using solution below we can avoid 80 swaps and perform only 24 swaps.
static void permutation(int[] a, int i, int j) {
for (; j < a.length && i < a.length; j++) {
int[] temp = null;
if (i != j) {
temp = swap(a, i, j);
System.out.println(Arrays.toString(temp));
}else{
temp = a;
}
permutation(temp, i + 1, i + 1);
}
}
public static void main(String[] args) {
int[] a = { 0, 1, 2, 3 };
permutation(a, 0, 0);
}
Another approach:
static ArrayList<ArrayList<Integer>> getPermutation(ArrayList<Integer> ints) {
if (ints.size() == 1) {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
list.add(ints);
return list;
} else {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
for (Integer i: ints) {
ArrayList<Integer> subList = new ArrayList<>(ints);
subList.remove(i);
ArrayList<ArrayList<Integer>> subListNew = getPermutation(subList);
for (ArrayList<Integer> _list: subListNew) {
ArrayList<Integer> local = new ArrayList<>();
local.add(i);
local.addAll(_list);
list.add(local);
}
}
return list;
}
}
This method first selects an element, removes it and obtains a sub-list, then produces a permutation of the sub-list until the list size becomes 1.
I like #tony200910041 approach but maybe someone would like a cleaner and more generic version of it:
public static <T> List<List<T>> getPermutations(List<T> list) {
if (list.size() == 1)
return Collections.singletonList(list);
List<List<T>> perms = new ArrayList<>();
for (T element: list) {
List<T> subList = new ArrayList<>(list);
subList.remove(element);
List<List<T>> subPerms = getPermutations(subList);
for (List<T> subPerm: subPerms) {
List<T> perm = new ArrayList<>();
perm.add(element);
perm.addAll(subPerm);
perms.add(perm);
}
}
return perms;
}
Sort the list before passing it to the getPermutations() function if you want your permutations in ascending order.
Try with
testPermu(start + 1);
You can do it simply without recursion
public static Integer[] permutate(int i)
{
int length = permus.length;
Integer[] result = new Integer[length];
List<Integer> chosen = new ArrayList<Integer>(Arrays.asList(permus));
int divider = 1;
for (int j=2; j<length; j++)
{
divider *= j;
}
for (int j=length; j>1; j--)
{
int index = i/divider;
result[length - j] = chosen.remove(index);
i = i - divider * (i/divider);
divider = divider / (j-1);
}
result[length -1] = chosen.remove(0);
return result;
}
How about the following algorithm (given in pseudocode)
iterate over elements:
pick one of the element at random
call function again on the remaining elements
if elements.size == 1
return or print
This should produce a valid permutation at each run. If you want all possible permutations, just accumulate as you iterate, then you should have all permutations.

Java sort LinkedList of LinkedLists into size order

I'm currently faced with this problem: I have a LinkedList that contains several LinkedLists containing longs, so:
LinkedList<LinkedList<Long>>() overalllList = new LinkedList<LinkedList<Long>();
After some code runs, the overall List gets filled with lists of longs of varying sizes. What I need to do is order the overallList so that it contains the lists of longs from smallest to largest.
I hope that makes sense.
So to clarify, I need this:
OverallList:
LinkedList<Long> (size 2) - first
LinkedList<Long> (size 245) - second
LinkedList<Long> (size 1000) - third
...etc
I'm not sure if using Collections would do this, or if I need to look at a custom comparator. Any input or advice would be appreciated.
Thanks
Here is one example of a method to do that,
// A "size()" comparator
private static Comparator<LinkedList<Long>> comp = new Comparator<LinkedList<Long>>() {
#Override
public int compare(LinkedList<Long> o1, LinkedList<Long> o2) {
return new Integer((o1 == null) ? 0 : o1.size()).compareTo((o2 == null) ? 0 : o2.size());
}
};
public static void main(String[] args) {
// LinkedList<LinkedList<Long>>() overalllList = new LinkedList<LinkedList<Long>();
// Note there is an extra () to the left of your overalllList.
LinkedList<LinkedList<Long>> overalllList = new LinkedList<LinkedList<Long>>();
LinkedList<Long> list3 = new LinkedList<Long>();
LinkedList<Long> list2 = new LinkedList<Long>();
LinkedList<Long> list1 = new LinkedList<Long>();
for (long i = 0; i < 5; i++) { // 5, or 1000
if (i < 2) {
list1.add(i);
}
if (i < 3) { // 3, or 245.
list2.add(i);
}
list3.add(i);
}
overalllList.add(list3);
overalllList.add(list2);
overalllList.add(list1);
System.out.println("Before: " + overalllList);
Collections.sort(overalllList, comp);
System.out.println("After: " + overalllList);
}
Output is
Before: [[0, 1, 2, 3, 4], [0, 1, 2], [0, 1]]
After: [[0, 1], [0, 1, 2], [0, 1, 2, 3, 4]]
List<List<Long>> overalllList = new LinkedList<List<Long>>();
overalllList.add(Arrays.asList(1L, 2L, 3L));
overalllList.add(Arrays.asList(4L, 5L, 6L, 7L, 8L));
overalllList.add(Arrays.asList(9L));
Collections.sort(overalllList, new Comparator<List<Long>>() {
#Override
public int compare(List<Long> list1, List<Long> list2) {
return list1.size() - list2.size();
}
});

Categories