Retrieve all value pairs from List<Integer> - java

For example I have a List<Integer> object with the following:
3, 6, 5, 3, 3, 6
The result would be 3 and 6. How can I create a function that tests for duplicates and then returns 1 value of the duplicate (not the pair, just one in the pair)? One problem that might occur is if there are quadruple values: 3, 4, 5, 3, 8, 3, 3 Then I would like to return 3 and 3. How can I accomplish this?

I would go through the list counting the number of instances of each one (storing them in a map) and then create a new list from the map:
List<Integer> values = // the list of values you have
Map<Integer,Integer> counts = new HashMap<Integer,Integer>();
for(Integer value : values) {
if(counts.containsKey(value)) {
counts.put(value, counts.get(value)+1);
} else {
counts.put(value, 1);
}
}
List<Integer> resultValues = new ArrayList<Integer>();
for(Integer value : counts.keySet()) {
Integer valueCount = counts.get(value);
for(int i=0; i<(valueCount/2); i++) { //add one instance for each 2
resultValues.add(value);
}
}
return resultValues;
This avoids the O(nlogn) behavior of sorting the values first, working in O(n) instead.

I think the "map" way by #RHSeeger is good enough. Here I just suggest another way, just for 'fun', so that u may take a look. It kind of give a stable result: first completed pairs appears first:
List<Integer> values = ....;
List<Integer> result = new ArrayList<Integer>();
Set<Integer> unpairedValues = new HashSet<Integer>();
for (int i : values) {
if (unpairedValues.contains(i)) {
result.add(i);
unpairedValues.remove(i);
} else {
unpairedValues.add(i);
}
}
// result contains what u want

One possible way in pseudo code:
sortedList = sort (list)
duplicates = empty list
while (length (list) > 1)
{
if (list [0] == list [1] )
{
duplicates.append (list [0] )
list.removeAt (0)
}
list.removeAt (0);
}

// ArrayList<Integer> list = {3, 6, 5, 3, 3, 6}
Collections.sort(list);
ArrayList<Integer> pairs = new ArrayList<Integer>();
int last = Integer.MIN_VALUE; // some value that will never appear in the list
for (Integer cur : list) {
if (last == cur) {
pairs.add(cur);
last = Integer.MIN_VALUE; // some value that will never appear in the list
} else {
last = cur;
}
}
System.out.println(Arrays.toString(pairs.toArray()));
Will output
[3, 6]
** Edit **
Slightly better algorithm, modifies the given list
// ArrayList<Integer> list = {3, 6, 5, 3, 3, 6}
Collections.sort(list);
int index = 1, last;
while (index < list.size()) {
last = list.remove(index - 1);
if (list.get(index - 1) == last) {
index++;
}
if (index == list.size()) {
list.remove(index - 1);
}
}

Related

Create a list of List from an Array

How can i create a list of List from Array eg:
int[] arr = {3, 1, 5, 8, 2, 4}.
Such that the lists in the List have only two elements eg:
[[3,1], [5,8], [2,4]].
So far i have tried code below but it return only lists with one element,I can't figure out where i went wrong.
class ListList {
public static List<List<Integer>> listOfList(int[] num){
List<List<Integer>> arrList = new ArrayList<>();
for(int i = 0 ; i<num.length;i++){
List<Integer> list = new ArrayList<>();
if(list.size() !=2){
list.add(num[i]);
}
arrList.add(list);
}
return arrList;
}
}
Result: [[3], [1], [5], [8], [2], [4]].
Here's a generic one:
var arr = new int[] {3, 1, 5, 8, 2, 4};
var batchSize = 2;
List<List<Integer>> lists = IntStream.range(0, arr.length)
.mapToObj(index -> Map.entry(index, arr[index]))
.collect(Collectors.groupingBy(e -> e.getKey() / batchSize))
.values().stream()
.map(entries -> entries.stream().map(Map.Entry::getValue).toList())
.toList();
System.out.println(lists);
Output:
[[3, 1], [5, 8], [2, 4]]
You are basically creating a mapping of index->value and subsequently grouping by the batchSize to make splits
You are creating an empty list on each iteration, then you check if its size != 2 (of course it is) and add 1 element, finally you add list with 1 element to result list, which is not what you need.
Move list creation out of loop and add elements to it. When its size == 2, add current list to result list and create a new one.
class ListList {
public static List<List<Integer>> listOfList(int[] num) {
List<List<Integer>> arrList = new ArrayList<>();
List<Integer> list = new ArrayList<>();
for(int i = 0; i < num.length; i++) {
if(list.size() == 2) {
arrList.add(list);
list = new ArrayList<>();
}
list.add(num[i]);
}
if(list.size() != 0) {
arrList.add(list);
}
return arrList;
}
}
If your input size can be odd, then you would also add list of length 1 to result list. If you don't want to, add aditional checks.
If you're certain that the list has an even number of values, you can do it like this.
create a list of lists.
taking two at a time, put each in a separate list
add that list to the list of lists
int [] arr ={3, 1, 5, 8, 2, 4};
List<List<Integer>> list = new ArrayList<>();
for (int i = 0; i < arr.length; i+=2) {
List<Integer> temp = Arrays.asList(arr[i], arr[i+1]);
list.add(temp);
}
System.out.println(list);
prints
[[3, 1], [5, 8], [2, 4]]
If you list is of odd length, change the assignment to
List<Integer> temp = arr.length - i >= 2 ? Arrays.asList(arr[i], arr[i+1]) :
Arrays.asList(arr[i]);
And here is a different take on the idea suggested by Dhrubajyoti Gogoi.
stream the indices.
use integer math to divide into groups, mapping to a list
and return the values as a collection of lists.
int groupSize = 2;
Collection<List<Integer>> result =
IntStream.range(0, arr.length)
.mapToObj(Integer::valueOf)
.collect(Collectors.groupingBy(
i -> i / groupSize,
Collectors.mapping(i -> arr[i],
Collectors.toList())))
.values();
Try this:
public static List<List<Integer>> listOfList(int[] num){
List<List<Integer>> arrList = new ArrayList<>();
for (int i = 0; i < num.length; i += 2) {
if (num.length > i + 1) {
arrList.add(List.of(num[i], num[i+1]));
} else {
arrList.add(List.of(num[i]));
}
}
return arrList;
}
In your example you always create a fresh list in the loop, so size is always 0 and never 2.

How to print out all elemets that is most frequent elemets in a array

I need to print out the numbers that are the most frequent elements in an array. Say that I have an int array like this:
int[] array = {1, 2, 3, 3, 3, 5}
I will then need to print out 3, as that is the most frequent element. But, I also need to print out the element that appear as frequent. Lets say I have this array now:
int[] array = {1, 2, 3, 3, 3, 5, 5, 5, 6, 7, 7, 7}
I then need to print out (ordered) 3, 5 and 7, as all three off them are the most frequent elements together. So the output needs to look like this:
3
5
7
This is the code I have so far (it works for printing out only one off the most frequent numbers)
Arrays.sort(diceSumArray);
int maxCount = 1;
int index = 1;
int r = diceSumArray[0];
for (int i = 1; i < diceSumArray.length; i++) {
if (diceSumArray[i] == diceSumArray[i-1]) {
index++;
} else {
if (index > maxCount) {
maxCount = index;
r = diceSumArray[i-1];
}
index = 1;
}
}
// not sure where to put the print or if the code below is necessary
System.out.println(r);
if (index > maxCount) {
maxCount = index;
r = diceSumArray[diceSumArray.length -1];
}
A better way to do this would be using HashMap to achieve a linear time complexity, where you would iterate over the array, save the # of occurrences of each item, and return a list of those that occur the most:
private static List<Integer> getMostFreq(int[] arr){
List<Integer> list = new ArrayList<>();
if(arr == null || arr.length == 0)
return list;
HashMap<Integer, Integer> map = new HashMap<>();
for(int num : arr)
if(!map.containsKey(num))
map.put(num,1);
else
map.replace(num, map.get(num)+1);
int max = Integer.MIN_VALUE;
for(HashMap.Entry<Integer,Integer> item : map.entrySet())
if(item.getValue() > max)
max = item.getValue();
for(HashMap.Entry<Integer,Integer> item : map.entrySet())
if(item.getValue() == max)
list.add(item.getKey());
return list;
}

delete occurrences of an element if it occurs more than n times JAVA

public class EnoughIsEnough {
public static int[] deleteNth(int[] elements, int maxOccurrences){
int n = 0;
for(int b: elements){
for(int i =0 , i< elements.length;i++) {
if(elements[b] == elements[i]){
n++;
}
if (n > maxOccurrences) {
for(int k = b; k < elements.length -1 ; k ++) {
elements[k] = elements [k + 1];
}
}
}
}
return null;
}
}
Hey im a total programming newbie and only familiar with the very basics and I came a cross this problem:
I have to delete occurrences of an element if it occurs more than n times but I don't know if im getting close or not, I struggle to remove the occurrences out of the array and im not even sure if the code I wrote so far is accutally detecting them.
I would really appreciate if someone can help me to solve this problem.
Because of my low rank im not able to view solutions on code wars and googling this problem didn't bring me any closer because of to complex code I don't understand.
public class EnoughIsEnough {
public static int[] deleteNth(int[] elements, int maxOccurrences){
HashMap<Integer, Integer> occurence = new HashMap<>();
for(int i : elements) {
if(occurence.containsKey(i)) {
occurence.put(i, occurence.get(i) + 1);
} else {
occurence.put(i, 1);
}
}
List<Integer> al = new ArrayList<>();
for(int i : elements) {
if(occurence.get(i) < maxOccurrences) {
al.add(i);
}
}
int[] output = new int[al.size()];
for(int i=0;i<al.size(); i++) {
output[i] = al.get(i);
}
return output;
}
}
You need to remember which elements exceed the count so you don't add them to the returned array.
The best way to do that is to keep a frequency count of the elements in a map for easy referral.
int[] v = deleteNth(new int[] { 20, 37, 20, 21 }, 1); // return [20,37,21]
System.out.println(Arrays.toString(v));
v = deleteNth(new int[] { 1, 1, 2, 3, 3, 7, 2, 2, 2, 2 }, 3); // return [1, 1, 3, 3, 7, 2, 2, 2]
System.out.println(Arrays.toString(v));
Prints
[20, 37, 21]
[1, 1, 2, 3, 3, 7, 2, 2]
Here is the method. As numbers are added to the return list, the map records them by incrmementing a count associated with the number. If the count exceeds the maxOccurrences allowed, it is not added to the list when encountered.
public static int[] deleteNth(int[] elements,
int maxOccurrences) {
List<Integer> ret = new ArrayList<>();
Map<Integer, Integer> count = new HashMap<>();
for (int i : elements) {
count.compute(i, (k,v)-> v == null ? 1 : v + 1);
if (count.get(i) <= maxOccurrences) {
ret.add(i);
}
}
// here you could return the list or convert to an array (as I did) and return
// that.
return ret.stream().mapToInt(a->a).toArray();
}

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]]

Obtaining a powerset of a set in 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);
}

Categories