जावा में एक सेट के एक अधिकार प्राप्त करना


86

का अधिकार {1, 2, 3}है:

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

मान लें कि मेरे पास Setजावा में है:

Set<Integer> mySet = new HashSet<Integer>();
mySet.add(1);
mySet.add(2);
mySet.add(3);
Set<Set<Integer>> powerSet = getPowerset(mySet);

मैं जटिलता के सर्वोत्तम संभव क्रम के साथ फ़ंक्शन getPowerset कैसे लिखूं? (मुझे लगता है कि यह O (2 ^ n) हो सकता है।)


7
मान लें कि आपके पास कॉन्फ़िगरेशन का एक सेट है - "A", "B" और "C" -, जो कि किसी मॉडल को Paradrize करने के लिए उपयोग किया जा सकता है, और आप यह देखना चाहते हैं कि कौन सा सबसे अच्छा परिणाम देता है - जैसे कि "A" "। एक संभावित समाधान यह होगा कि प्रत्येक सदस्य के अधिकार का परीक्षण किया जाए।
जोआ सिल्वा

7
यह सॉफ्टवेयर डेवलपर्स के लिए एक Google साक्षात्कार प्रश्न है। यह आपके मन की चपलता का परीक्षण करने के लिए एक विरोधाभासी समस्या है।
एरिक लेसिंसकी

यह एक वाजिब सवाल है। उदाहरण के लिए क्रिबेज के लिए स्कोरिंग फ़ंक्शन को लागू करने के लिए, आपको यह परीक्षण करना होगा कि क्या पॉवरसेट का कोई भी तत्व 15. तक बढ़ जाता है
जॉन

जवाबों:


101

हां, यह O(2^n)वास्तव में है, क्योंकि आपको उत्पन्न करने की आवश्यकता है, अच्छी तरह से, 2^nसंभव संयोजन। यहां जेनरिक और सेट का उपयोग करते हुए एक कार्यशील कार्यान्वयन है:

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;
}  

और एक परीक्षण, अपना उदाहरण इनपुट दिया:

 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);
 }

1
क्या सूची का उपयोग करने के बजाय Iterator का उपयोग करना तेज़ होगा? जैसे: सेट <टी> बाकी = नया हैशसेट <टी> (ओरिजिनल); Iterator <T> i = rest.iterator (); टी सिर = i.next (); मैं हटाता हूँ(); ?
दीमनाथ

1
@CosminVacaroiu ... और क्या यह संभवतः कर सकता है?
user253751

3
क्या आपको यकीन है O(2^n)? पावर सेट में सेट की संख्या है, लेकिन प्रत्येक सेट को मेमोरी में बनाया जाना है, जो सेट आकार को कम से कम आनुपातिक लेता है। वुल्फराम अल्फा के अनुसार, यह इसमें है O(n * 2^n): वुल्फराम अल्फा क्वेरी
फैबियन

1
अगर सेट का आकार 10 ^ 5 के क्रम में है तो भी क्या यह काम करेगा?
bane19

1
@ गौरवशंकर 2 ^ 100 = 2 ^ (10 ^ 2) पहले से ही 10 ^ 30 से बड़ा है। आप गणना करने वाले गवाह को किसी भी बात पर नहीं देखेंगे जो कि आप इसकी गणना के लिए ट्यूरिंग-मशीन पर कर रहे हैं।
कार्ल रिक्टर

31

दरअसल, मैंने वह कोड लिखा है जो वही करता है जो आप O (1) में पूछ रहे हैं। सवाल यह है कि आप सेट के साथ आगे क्या करने की योजना बना रहे हैं । यदि आप बस size()उस पर कॉल करने जा रहे हैं , तो वह ओ (1) है, लेकिन यदि आप इसे पुनरावृत्त करने जा रहे हैं तो यह स्पष्ट है O(2^n)

contains()होगा O(n), आदि।

क्या आपको वास्तव में इसकी आवश्यकता है?

संपादित करें:

यह कोड अब अमरूद में उपलब्ध है , जिसे विधि के माध्यम से उजागर किया गया है Sets.powerSet(set)


मुझे हर उपसमुच्चय पर पुनरावृति करने की आवश्यकता है
मैनुएल आराज़

लेकिन क्या आपको हर सबसेट को स्टोर करने की जरूरत है ?
finnw


क्या होगा यदि मैं वास्तव में k तत्वों के साथ पावरसेट चाहता हूं? क्या आपका कोड उसके लिए कुशल है?
ईयाल


12

यहां एक समाधान है जहां मैं एक जनरेटर का उपयोग करता हूं, लाभ, पूरे पावर सेट को एक बार में संग्रहीत नहीं किया जाता है ... इसलिए आप इसे स्मृति में संग्रहीत किए जाने की आवश्यकता के बिना एक-एक करके उस पर पुनरावृति कर सकते हैं। मुझे लगता है कि यह एक बेहतर विकल्प है ... ध्यान दें कि जटिलता समान है, हे (2 ^ n), लेकिन स्मृति आवश्यकताओं को कम कर दिया जाता है (यह मानते हुए कि कचरा कलेक्टर व्यवहार करता है?))

/**
 *
 */
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;
    }

}

इसे कॉल करने के लिए, इस पैटर्न का उपयोग करें:

        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);
        }

यह मेरी परियोजना यूलर लाइब्रेरी से है ... :)


अमरूद एक के समान काम करता है, लेकिन 32 तत्वों तक सीमित है। यह अनुचित नहीं है क्योंकि 2 ** 32 शायद बहुत अधिक पुनरावृत्तियां हैं। यह आपकी तुलना में भी कम मेमोरी का उपयोग करता है क्योंकि यह केवल जरूरत पड़ने पर AbstractSet जनरेट करता है। अमरूद के खिलाफ अपना कोड आज़माएं जहां आप 10,000 तत्वों में से केवल 1 को प्रिंट करते हैं, और एक बड़ा उदाहरण बनाते हैं। मुझे यकीन है कि अमरूद एक तेज हो जाएगा।
ईयाल

@, मुझे यकीन है कि यह करता है, मैंने कभी दावा नहीं किया। मैंने इसे स्वयं लिखा है, यह उत्पादन कोड के लिए अभिप्रेत नहीं है। यह एल्गोरिदम में एक अभ्यास था।
st0le

1
लघु टिप्पणी: आपका 'रिटर्नसेट' एक ट्रीसेट है, जिसके लिए आवश्यक है कि इसकी वस्तुएँ तुलनीय हों। यह मामला नहीं हो सकता है। इसे HashSet या LinkedHashSet के लिए स्वैप करने पर विचार करें
Joris Kinable

10

यदि n <63, जो कि एक उचित धारणा है, क्योंकि आप मेमोरी से बाहर निकलेंगे (जब तक कि एक पुनरावृत्ति कार्यान्वयन का उपयोग नहीं कर रहे हैं) वैसे भी पावर सेट के निर्माण की कोशिश कर रहा है, यह करने के लिए एक अधिक संक्षिप्त तरीका है। बाइनरी ऑपरेशन Math.pow(), मास्क के लिए तेजी से और सरणियों के रास्ते हैं, लेकिन किसी भी तरह जावा उपयोगकर्ता उनसे डरते हैं ...

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;

लूप के लिए समाप्ति की स्थिति i <(1 << n - 1) के बजाय i <(2 << n - 1) होनी चाहिए।
बेज़ुस्सज

धन्यवाद @bazeusz, मैंने इसे बदल दिया है i < (1 << n)जो समकक्ष है।
एंड्रयू माओ

चूंकि बिट वार ऑपरेशन का उपयोग किया जाता है, मुझे लगता है कि ((i >> j) &1) == 1इसके बजाय (i >> j) % 2 == 1 इस्तेमाल किया जा सकता है। इसके अलावा, longहस्ताक्षर किए गए हैं, तो क्या आपको लगता है कि अतिप्रवाह के लिए जांच से समझ में आता है?
रवि तिवारी

9

यहाँ एक ट्यूटोरियल है जो आपको कोड सहित वास्तव में चाहिए। आप सही हैं कि जटिलता O (2 ^ n) है।


2
जटिलता नहीं है (n * 2 ^ n)? क्योंकि बाइनरी स्ट्रिंग लंबाई n की है, और मुख्य लूप के प्रत्येक पुनरावृत्ति में हम पूरे बाइनरी स्ट्रिंग को पुनरावृत्त करते हैं।
मैगी

1
ट्यूटोरियल महान है लेकिन मैंने इस तकनीक का उपयोग हैकररैंक समस्या को हल करने में किया है: यह परीक्षण के मामलों में से केवल आधा ही पारित हुआ, और अन्य आधे समय-समय पर या रनटाइम त्रुटि के कारण विफल हुए।
यूजेनिया ओजीर्ना

7

मैं @ उपाय पर आधारित एक अन्य समाधान के साथ आया हूं वह विचार है। शायद सबसे सुरुचिपूर्ण नहीं है, लेकिन यहाँ जैसा कि मैं इसे समझता हूँ:

आइए, सपाट (S) = {{1}, {2}, {3}} का शास्त्रीय सरल उदाहरण लेते हैं। हमें पता है कि सबसेट की संख्या पाने का सूत्र 2 ^ n (7 + खाली सेट) है। इस उदाहरण के लिए 2 ^ 3 = 8 सबसेट।

प्रत्येक उपसमूह को खोजने के लिए हमें नीचे दी गई रूपांतरण तालिका में दिखाए गए द्विआधारी प्रतिनिधित्व को 4-7 दशमलव में बदलने की आवश्यकता है:

रूपांतरण तालिका

यदि हम पंक्ति द्वारा तालिका पंक्ति को पार करते हैं, तो प्रत्येक पंक्ति का एक सबसेट होगा और प्रत्येक सबसेट का मान सक्षम बिट्स से आएगा।

बिन मान अनुभाग में प्रत्येक स्तंभ मूल इनपुट सेट में सूचकांक स्थिति से मेल खाता है।

यहाँ मेरा कोड:

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;
}

}

5

यदि आप ग्रहण संग्रह (पूर्व में GS संग्रह ) का उपयोग कर रहे हैं , तो आप powerSet()सभी 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]]

नोट: मैं ग्रहण संग्रहों के लिए एक कमिटेटर हूं।


क्या आप अपने समाधान का कोड साझा और समझा सकते हैं?
कोनराड होफ़नर

3
: आप यहाँ कोड के माध्यम से देख सकते हैं github.com/goldmansachs/gs-collections/blob/...
क्रेग पी Motlin

4

मैं एक ऐसे समाधान की तलाश कर रहा था जो यहां तैनात लोगों की तरह विशाल न हो। यह जावा 7 को लक्षित करता है, इसलिए इसे 5 और 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;

परीक्षण करने के लिए यहां कुछ उदाहरण कोड दिए गए हैं:

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()));
}

क्या PowerSetofNodes () एक "}" को अंत में याद नहीं कर रहा है?
पीटर मोर्टेंसन

3

ऊपर दिए गए समाधानों में से कुछ तब झेलते हैं जब सेट का आकार बड़ा होता है क्योंकि वे एकत्रित होने के लिए बहुत अधिक कचरा पैदा कर रहे होते हैं और डेटा की प्रतिलिपि बनाने की आवश्यकता होती है। हम इससे कैसे बच सकते हैं? हम इस तथ्य का लाभ उठा सकते हैं कि हम जानते हैं कि परिणाम सेट का आकार कितना बड़ा होगा (2 ^ n), एक सरणी का प्रचार करें जो कि बड़ा है, और बस इसके अंत में संलग्न करें, कभी भी नकल न करें।

स्पीडअप एन के साथ जल्दी बढ़ता है। मैंने इसकी तुलना ऊपर जोआ सिल्वा के समाधान से की। मेरी मशीन पर (सभी माप अनुमानित), n = 13 5x तेज है, n = 14 7x है, n = 15 12x है, n = 16 25x है, n = 17 75x है, n = 18 140x है। ताकि कचरा निर्माण / संग्रह और नकल में हावी हो रहा है अन्यथा समान रूप से बड़े-ओ समाधान प्रतीत होते हैं।

शुरुआत में सरणी को देखते हुए इसे गतिशील रूप से बढ़ने देने की तुलना में एक जीत प्रतीत होती है। N = 18 के साथ, गतिशील रूप से बढ़ते हुए समग्र रूप से दोगुना होता है।

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;
}

3

निम्नलिखित समाधान मेरी पुस्तक " कोडिंग साक्षात्कार: प्रश्न, विश्लेषण और समाधान " से उधार लिया गया है :

एक सरणी में कुछ पूर्णांकों का चयन किया जाता है जो संयोजन बनाते हैं। बिट्स के एक सेट का उपयोग किया जाता है, जहां प्रत्येक बिट सरणी में पूर्णांक के लिए खड़ा होता है। यदि i-th वर्ण संयोजन के लिए चुना गया है, तो i-th बिट 1 है; अन्यथा, यह 0. है। उदाहरण के लिए, तीन बिट्स का उपयोग सरणी के संयोजन के लिए किया जाता है [1, 2, 3]। यदि पहले दो पूर्णांक 1 और 2 को एक संयोजन बनाने के लिए चुना जाता है [1, 2], तो संबंधित बिट्स {1, 1, 0} हैं। इसी तरह, एक और संयोजन [1, 3] से संबंधित बिट्स {1, 0, 1} हैं। यदि हम n बिट्स के सभी संभव संयोजनों को प्राप्त कर सकते हैं, तो हम लंबाई n के साथ एक सरणी के सभी संयोजनों को प्राप्त करने में सक्षम हैं ।

एक संख्या बिट्स के एक सेट से बना है। N बिट्स के सभी संभावित संयोजन 1 से 2 ^ n -1 तक की संख्या के अनुरूप हैं । इसलिए, 1 और 2 ^ n -1 के बीच की सीमा में प्रत्येक संख्या, लंबाई n के साथ एक सरणी के संयोजन से मेल खाती है । उदाहरण के लिए, संख्या 6 बिट्स {1, 1, 0} से बना है, इसलिए संयोजन [1, 2] को उत्पन्न करने के लिए पहले और दूसरे वर्ण को सरणी [1, 2, 3] में चुना जाता है। इसी प्रकार, बिट्स के साथ 5 संख्या {1, 0, 1} संयोजन [1, 3] से मेल खाती है।

इस समाधान को लागू करने के लिए जावा कोड नीचे की तरह दिखता है:

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;
}

विधि वेतन वृद्धि बिट्स के एक सेट में दर्शाई गई संख्या को बढ़ाती है। एल्गोरिथ्म 1 बिट्स को सबसे सही बिट से 0 बिट्स मिलने तक साफ़ करता है। यह तब सबसे सही 0 बिट सेट करता है। 1. उदाहरण के लिए, बिट्स के साथ संख्या 5 को बढ़ाने के लिए {1, 0, 1}, यह दाईं ओर से 1 बिट्स को साफ करता है और सबसे सही 0 बिट को 1. सेट करता है। {6 नंबर के लिए 1, 1, 0}, जो कि 1 से 5 बढ़ने का परिणाम है।


दो चीजें जो मैंने संशोधित कीं: नंबर.लिफ्टिंग (या बिट्स.साइज ()) के बजाय गेटकॉम्बिनेशन में लूपिंग, एक बिट्स.लिफ्टिंग () को पुनरावृत्त कर सकता है, जो स्पीड-जनरेशन को थोड़ा बढ़ा देता है। अंत में, मैंने अपनी समस्या के लिए आकार के आधार पर सबसेट को हल कर दिया।
BoLe

3

यहाँ एक आसान पुनरावृत्ति हे (2 ^ n) समाधान है:

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;
}

यह समाधान O (2 ^ n) स्थान का भी उपयोग करता है जो बड़े इनपुट सेटों के लिए बहुत अधिक होगा। पुनरावर्ती के स्थान पर स्टैक या कतार का उपयोग करके पुनरावर्ती परिभाषा का पालन करना बेहतर है।
rossb83

2
import java.util.Set;
import com.google.common.collect.*;

Set<Set<Integer>> sets = Sets.powerSet(ImmutableSet.of(1, 2, 3));

1

यदि S, N तत्वों के साथ एक परिमित सेट है, तो S के पावर सेट में 2 ^ N तत्व होते हैं। केवल अधिकार के तत्वों की गणना करने का समय 2 ^ N है, इसलिए O(2^N)पावरसेट के निर्माण (उत्सुकतापूर्वक) की समय जटिलता पर एक कम बाध्य है।

सीधे शब्दों में कहें, किसी भी गणना जिसमें कि पॉवरसेट्स बनाना शामिल है, एन के बड़े मूल्यों के लिए पैमाने पर नहीं जा रहा है। कोई भी चालाक एल्गोरिथ्म आपकी मदद नहीं करेगा ... इसके अलावा पावरसेट बनाने की आवश्यकता को टालें!


1

पुनरावृत्ति के बिना एक तरीका निम्नलिखित है: एक बाइनरी मास्क का उपयोग करें और सभी संभव संयोजनों को बनाएं।

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;

    }

}

1

कलन विधि:

इनपुट: सेट करें [], set_size 1. पॉवर सेट का आकार पाएं powet_set_size = pow (2, set_size) इस उपसमूह के लिए सेट से प्रिंट ith तत्व सेट करें (बी) सबसेट के लिए प्रिंट सेपरेटर अर्थात, नईलाइन

#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;
}


1

यह मेरा पुनरावर्ती समाधान है जो जावा जेनरिक का उपयोग करके किसी भी सेट की शक्ति प्राप्त कर सकता है। इसका मुख्य विचार इनपुट सरणी के प्रमुख को बाकी सरणी के सभी संभावित समाधानों के साथ निम्नानुसार संयोजित करना है।

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);
    }
}

यह आउटपुट होगा:

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

1

एक और नमूना कार्यान्वयन:

 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();
        }
    }

1

लंबोदर के साथ मेरा यही दृष्टिकोण है।

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());
        }

या समानांतर में (समानांतर देखें) टिप्पणी:

इनपुट सेट का आकार: 18

लॉजिकल प्रोसेसर: 8 à 3.4GHz

प्रदर्शन में सुधार: 30%


1

टी का एक उप-सेट कोई भी सेट है जिसे टी के शून्य या अधिक तत्वों को हटाकर बनाया जा सकता है। बिना फ़र्स्ट उप सबसेट पहले तत्व को याद कर रहे हैं कि टी के सबसेट जोड़ता है और लूप के लिए पहले तत्व के साथ सबसेट जोड़ने के साथ सौदा होगा। उदाहरण के लिए, यदि t में "[1", "2", "3"], अनुपलब्ध तत्व हैं तो [[""], ["2"], ["3"], ["2", "3" "]] और लूप इन तत्व के सामने" 1 "चिपकाएगा और इसे नएसेट में जोड़ देगा। तो हम [[""], ["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;
    }

कृपया प्रदान किए गए कोड के साथ एक छोटी व्याख्या जोड़ने पर विचार करें।
मिर्ज़ा सिसिक

यह भी संकलित नहीं करता है, लगता है कि कुछ काल्पनिक जावा संस्करण में लिखा गया है। एक सूचकांक के साथ Setएक getविधि नहीं है , न ही एक subSetविधि; 1stवैध पहचानकर्ता नहीं है (मुझे लगता है कि lstइसका मतलब था)। सूचियों के सभी सेटों को बदलें और यह लगभग संकलन करता है ...
john16384

0
// 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;
    }

}

ढेर अतिप्रवाह में आपका स्वागत है। हो सकता है कि आप इस उत्तर को कुछ पाठ के साथ समझाना चाहें कि यह क्या कर रहा है और यह प्रश्न पूछने वाले की समस्या को हल करता है।
लाचलान गूडवे-कुक

0

मुझे हाल ही में कुछ इस तरह का उपयोग करना था, लेकिन पहले सबसे छोटे सब्लिस्ट (1 तत्व, फिर 2 तत्व, ...) की आवश्यकता थी। मैं खाली या पूरी सूची को शामिल नहीं करना चाहता था। इसके अलावा, मुझे उन सभी सब्लिस्टों की सूची की आवश्यकता नहीं थी, जिन्हें मुझे प्रत्येक के साथ कुछ सामान करने की आवश्यकता थी।

पुनरावृत्ति के बिना ऐसा करना चाहते थे, और निम्नलिखित के साथ आया ("सामान कर" के साथ एक कार्यात्मक इंटरफ़ेस में सार):

@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
}

इस तरह, विशिष्ट लंबाई के सब्लिस्ट के लिए इसे सीमित करना भी आसान है।


0
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

फिर भी एक और समाधान - java8 + स्ट्रीमिंग एपीआई के साथ यह आलसी है और इसका आदेश दिया जाता है ताकि यह "सीमा ()" के साथ उपयोग होने पर सही सबसेट वापस कर दे।

 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()));
}

और ग्राहक कोड है

@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);

}

/ * प्रिंट: [] [ए] [बी] [सी] [डी] [ई] [ए, बी] [ए, सी] [बी, सी] * /


0

हम पुनरावृत्ति का उपयोग किए बिना या उसके बिना सेट की गई शक्ति को लिख सकते हैं। यहाँ पुनरावृत्ति के बिना एक प्रयास है:

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;
}

0

यहां पावर सेट जनरेट करना है। विचार पहले है = S[0]और छोटे सेट हो S[1,...n]

छोटेसैट के सभी सबसेट की गणना करें और उन्हें सभी सदस्यता में डालें।

Allsubsets में प्रत्येक सबसेट के लिए, इसे क्लोन करें और सबसेट में पहले जोड़ें।

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;
}

0
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>();
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.