I have the following array list which contains the following
point ids (1,2,3,4,1,8,5,6,8,9,7,9). I am using Java 7
I was wondering how it could be split into sublists i.e the sublists below
(1,2,3,4,1)
(8,5,6,8)
(9,7,9)
I have had problems trying to use a loop within a loop (i.e check each point
from the outer loop with each of the other points in the inner loop) to get
index positions (starPosIndex and endPosIndex) where there are duplicate point ids and ArrayList.sublist(startPosIndex,endPosIndex) to get the correct sublist
int startPos = 0;
int endPos = 0;
for (int j = 0; j < polygonList3.size(); j++){
Point pointToCheck = polygonList3.get(j);
for (int k = 1; k < polygonList3.size(); k++){
Point pointToCheck2 = polygonList3.get(k);
if (pointToCheck.getID() == pointToCheck2.getID()){
startPos = startPos + endPos;
endPos = endPos + k;
//startPos = startPos + endPos;
//for (int startPos = j; startPos < polygonList3.size(); startPos = (startPos) + endPos) {
//endPos = Math.min(startPos + endPos, polygonList3.size());
finalPolygonLists.add(new ArrayList<Point>(polygonList3.subList(startPos, endPos)));//originalPtsSublist2);
//}
}
}
I would solve it in the following manner:
Allocate a HashSet to contain unique values encountered
Allocate a new list for the first sublist
Iterate over the whole list, adding each value to the set. When we encounter a value that is already in the set, we are done with the first sublist, so clear the set, and allocate a new sublist
After iteration, you will have your list of sublists, obtained in O(n) runtime
You can walk along the list, and create slices of the list (using List#subList) as you go. This can be done efficiently, by always checking whether the first element of the current segment of the list appears somewhere else in the list. If it does, you can store this "slice", and continue with the "tail" of the list. If it doesn't, you are finished (and the tail of the list may or may not be part of the result - that's up to you)
Implemented here as an example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListSlicing
{
public static void main(String[] args)
{
runTest(1,2,3,4,1,8,5,6,8,9,7,9);
runTest(1,2,3,4);
runTest(1,1,1,1);
runTest(1,2,1,2,1,2,1,2,1,2,1,2);
runTest();
}
private static void runTest(Integer ... numbers)
{
List<Integer> list = Arrays.asList(numbers);
System.out.println("Input: "+list);
System.out.println("Output: "+slices(list));
}
private static <T> List<List<T>> slices(List<T> input)
{
List<List<T>> slices = new ArrayList<List<T>>();
List<T> current = input;
while (current.size() > 0)
{
T first = current.get(0);
int appearance = current.subList(1, current.size()).indexOf(first);
if (appearance == -1)
{
slices.add(current);
return slices;
}
List<T> slice = current.subList(0, appearance+2);
slices.add(slice);
current = current.subList(appearance+2, current.size());
}
return slices;
}
}
The output is
Input: [1, 2, 3, 4, 1, 8, 5, 6, 8, 9, 7, 9]
Output: [[1, 2, 3, 4, 1], [8, 5, 6, 8], [9, 7, 9]]
Input: [1, 2, 3, 4]
Output: [[1, 2, 3, 4]]
Input: [1, 1, 1, 1]
Output: [[1, 1], [1, 1]]
Input: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
Output: [[1, 2, 1], [2, 1, 2], [1, 2, 1], [2, 1, 2]]
Input: []
Output: []
The following code tracks the last position for each number and as soon as it founds a duplicate, it will create the sublist and clears all previously tracked entries.
List<Integer> list = Arrays.asList( 1,2,3,4,1,8,5,6,8,9,7,9);
List<List<Integer>> sublists = new ArrayList<>();
Map<Integer,Integer> lastPos = new HashMap<>();
for(int i = 0; i < list.size(); i++) {
Integer current = list.get(i);
if(lastPos.containsKey(current)){
sublists.add(list.subList(lastPos.get(current), i+1));
lastPos.clear();
} else {
lastPos.put(current, i);
}
}
System.out.println(sublists);
I have n lists, for example:
L_1 = [a_11, a_12, ...]
L_2 = [a_21, a_22, ...]
...
L_n = [a_n1, a_n2, ...]
where ith list has k_i elements.
And now, I want to generate all n-elements list, where ith element is from L_i, I mean:
[a_11, a_21, ..., a_n1]
[a_11, a_21, ..., a_n2]
...
[a_11, a_22, ..., a_n1]
[a_11, a_22, ..., a_n2]
...
[a_12, a_21, ..., a_n1]
[a_12, a_21, ..., a_n2]
...
[a_12, a_22, ..., a_n1]
[a_12, a_22, ..., a_n2]
...
The total number of lists shoulbe be equal to k_1*k_2*...k_n. Could you describe pseudo-code of this algorithm or use Java code? I can do this using nested for-loops when number of lists is hardcoded, but I'm completely blocked when n is customizable at runtime.
Ok, I implemented this algorithm.
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class PermutationGenerator {
private List<List<Integer>> result;
private List<List<Integer>> data;
public List<List<Integer>> permutate(List<List<Integer>> data) {
this.data = data;
this.result = Lists.newArrayList();
List<Integer> integers = new ArrayList<Integer>(Collections.nCopies(data.size(), 0));
foo(0, data.size() - 1, integers);
return result;
}
private void foo(Integer index, Integer maxIndex, List<Integer> output) {
List<Integer> list = data.get(index);
for (int i = 0; i < list.size(); i++) {
output.set(index, list.get(i));
if (index == maxIndex) {
result.add(Lists.newArrayList(output));
} else {
foo(index + 1, maxIndex, output);
}
}
}
}
Test class:
import com.google.common.collect.Lists;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
public class PermutationGeneratorTest {
#Test
public void test() throws Exception {
// given
PermutationGenerator pg = new PermutationGenerator();
List<Integer> list1 = Lists.newArrayList(1, 2, 3);
List<Integer> list2 = Lists.newArrayList(4, 5);
List<Integer> list3 = Lists.newArrayList(6, 7, 8, 9);
List<List<Integer>> input = Lists.newArrayList(list1, list2, list3);
// when
List<List<Integer>> output = pg.permutate(input);
// then
print(output);
}
private void print(List<List<Integer>> output) {
for (List<Integer> list : output) {
System.out.println(Arrays.toString(list.toArray()));
}
System.out.println("TOTAL: " + output.size());
}
}
Output:
[1, 4, 6]
[1, 4, 7]
[1, 4, 8]
[1, 4, 9]
[1, 5, 6]
[1, 5, 7]
[1, 5, 8]
[1, 5, 9]
[2, 4, 6]
[2, 4, 7]
[2, 4, 8]
[2, 4, 9]
[2, 5, 6]
[2, 5, 7]
[2, 5, 8]
[2, 5, 9]
[3, 4, 6]
[3, 4, 7]
[3, 4, 8]
[3, 4, 9]
[3, 5, 6]
[3, 5, 7]
[3, 5, 8]
[3, 5, 9]
TOTAL: 24
As you have already found out yourself, the usual trick is to think of the lists a non-uniform version of the g-adic numbers and do carry increment on the list index positions:
When you have n lists, you have n index positions in those lists:
index_pos = [i0, ..., in-1]
The trick is now as follows:
start with index_pos = [0, 0, ...]
increment index_pos[0].
If the result is larger or equal to lists[0].size(), set index_pos[0] = 0 and increment index_pos[1].
if index_pos[1] is larger than or equal to lists[1].size() ... and so on
You are done when index_pos[n - 1] overflows
An non-recursive solution in Java would be like
public static <T> void permute(
final List<List<T>> lists,
final Consumer<List<T>> consumer
)
{
final int[] index_pos = new int[lists.size()];
final int last_index = lists.size() - 1;
final List<T> permuted = new ArrayList<T>(lists.size());
for (int i = 0; i < lists.size(); ++i) {
permuted.add(null);
}
while (index_pos[last_index] < lists.get(last_index).size()) {
for (int i = 0; i < lists.size(); ++i) {
permuted.set(i, lists.get(i).get(index_pos[i]));
}
consumer.accept(permuted);
for (int i = 0; i < lists.size(); ++i) {
++index_pos[i];
if (index_pos[i] < lists.get(i).size()) {
/* stop at first element without overflow */
break;
} else if (i < last_index) {
index_pos[i] = 0;
}
}
}
}
Usage example:
public static void main(String[] args)
{
final List<List<Integer>> lists = new ArrayList<List<Integer>>();
final List<Integer> list0 = new ArrayList<Integer>();
list0.add(0);
list0.add(1);
list0.add(2);
list0.add(4);
lists.add(list0);
lists.add(list0);
lists.add(list0);
permute(lists, (permutation -> System.out.println(permutation)));
}
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.
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);
}