Obtaining a powerset of a set in Java

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

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

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

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

相关标签:
26条回答
  • 2020-11-22 11:40

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

    0 讨论(0)
  • 2020-11-22 11:41

    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);
     }
    
    0 讨论(0)
  • 2020-11-22 11:42
    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();
            } 
        }
    }
    
    0 讨论(0)
  • 2020-11-22 11:43

    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;
    
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 11:43

    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();
            }
        }
    
    0 讨论(0)
  • 2020-11-22 11:44

    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).

    0 讨论(0)
提交回复
热议问题