寻找通用集合的幂集

huangapple 未分类评论52阅读模式
英文:

Finding the power set of a generic set

问题

我得到了一个问题要利用 Java 泛型并创建一个 Set 类我已经能够执行其他功能比如并集交集补集等都是使用这个 Set 类来实现的

但是我一直在面对的问题是如何找到所有的幂集我需要返回一个集合即幂集)。我从昨天开始一直在尝试解决这个问题但一直没有成功我尝试了实现二进制方法来找到幂集到目前为止我所做的一切都是基于问题的要求

public class Set<T extends Comparable> {

    private ArrayList<T> theSet;

    public Set(T[] theElements){
        theSet = new ArrayList<>();
        for(int i=0; i < theElements.length; i++){
            if(!checker(theElements[i]))
                theSet.add(theElements[i]);
        }
    }

    public ArrayList<T> getTheSet() {
        return theSet;
    }

    public Set powerSet(){
        long powerSetSize = (long)Math.pow(2, theSet.size());
        int counter, j;
        Set[] powerSet = new Set[(int)Math.pow(2, theSet.size())];
        T[] currentArray = null;

        for(counter=0; counter<powerSetSize; counter++){
            for(j=0; j<theSet.size(); j++){
                currentArray = (T[]) new Comparable[j+1];
                if((counter & (1 << j)) > 0)
                    currentArray[j] = theSet.get(j);
            }
            powerSet[counter] = new Set<>(currentArray);
        }

        return new Set<>((T[])powerSet);
    }

    public String toString(){
        String str = "{";
        for(int i=0; i<theSet.size(); i++){
            if(i < theSet.size()-1)
                str += theSet.get(i)+", ";
            else
                str += theSet.get(i)+"}";
        }
        return str;
    }
}
英文:

I had been given a question to utilize java generics and create a Set class. I have been able to perform other functions such as union, intersection, complement etc using this Set class.

But the problem i have been facing is with finding all the power sets. I am required to return a set (i.e the power set). I have been trying to solve this since yesterday but to no avail. I have tried implementing binary method to find the power sets. Everything that i have done so far is based on the requirements of the question!

public class Set&lt;T extends Comparable&gt; {

private ArrayList&lt;T&gt; theSet;

public Set(T[] theElements){
    theSet = new ArrayList&lt;&gt;();
    for(int i=0; i &lt; theElements.length; i++){
        if(!checker(theElements[i]))
            theSet.add(theElements[i]);
    }
}

public ArrayList&lt;T&gt; getTheSet() {
    return theSet;
}

public Set powerSet(){
    long powerSetSize = (long)Math.pow(2, theSet.size());
    int counter, j;
    Set[] powerSet = new Set[(int)Math.pow(2, theSet.size())];
    T[] currentArray = null;
    
    for(counter=0; counter&lt;powerSetSize; counter++){
        for(j=0; j&lt;theSet.size(); j++){
            currentArray = (T[]) new Comparable[j+1];
            if((counter &amp; (1 &lt;&lt; j)) &gt; 0)
                currentArray[j] = theSet.get(j);
        }
        powerSet
0
+
网站访问量
= new Set&lt;&gt;(currentArray); } return new Set&lt;&gt;((T[])powerSet); } public String toString(){ String str = &quot;{&quot;; for(int i=0; i&lt;theSet.size(); i++){ if(i &lt; theSet.size()-1) str += theSet.get(i)+&quot;, &quot;; else str += theSet.get(i)+&quot;}&quot;; } return str; } }

答案1

得分: 0

你可以尝试以下操作:

首先创建一个整数数组,其长度与你的基本集合长度相同,并将每个整数设置为零。请记住,由于需要一个空元素(即零),所以每个元素都按照其在基本集合中的位置进行编号,编号为基本集合位置 +1。然后,当然首先创建一个Set的集合,你将以此作为你的幂集返回。然后按照以下步骤遍历整数数组:通过将每个整数解析为Set集合中的相应元素,创建一个Set。然后将整数数组的第一个整数加一。如果数字大于基本集合的长度,则将数组中的下一个整数加一,将"溢出"的整数设置为数组中下一个整数+1。

这样,你应该能够遍历幂集的每种可能组合,并将它们添加到集合中。

public Set<Set<T>> powerSet(){
    int[] num = new int[list.size()];
    Arrays.fill(num, 0);
    Set<Set<T>> powerSet = new Set<>();
    do{
        powerSet.list.add(parse(num));
    }while (addNum(num)); // 循环遍历每种可能性
    powerSet.list.add(parse(num)); 
    // 因为当这是最后一个可能的增量时,方法返回false
    return powerSet;
}

// 将int[]转换为相应的Set
private Set<T> parse(int[] e){
    Set<T> s = new Set<>();
    for (int i = 0; i < e.length; i++) {
        if(e[i] != 0){
            s.list.add(list.get(e[i] - 1)); // 每个元素都有其编号
        }
    }
    return s;
}

// 增加计数器
// 如果这是最后一个可能的增量,则返回false
private boolean addNum(int[] e){
    e[0]++;
    for (int i = 0; i < e.length; i++) {
        if(e[i] > e.length - i){
            e[i] = 0;
            e[i + 1]++;
        }
    }
    for (int i = e.length - 1; i != 0; i--) {
        if(e[i] >= e[i - 1] && e[i] != 0){
            e[i - 1] = e[i] + 1;
        }
    }
    if(e[e.length - 1] == 1){
        return false;
    }
    return true;
}

[3, 43, 65, 32]的输出(以每个幂集的集合形式打印出来):

[]
[3]
[43]
[65]
[32]
[43, 3]
[65, 3]
[32, 3]
[65, 43]
[32, 43]
[32, 65]
[65, 43, 3]
[32, 43, 3]
[32, 65, 3]
[32, 65, 43]
[32, 65, 43, 3]

尽管这可能不是解决问题的最优雅方式,但似乎是有效的。另外,我不清楚问题的要求,所以这个答案可能不合适。

英文:

You could try the following:

First create and Array of Integers with length of your basic set, setting every Integer to zero. Keep in mind that every Element is numbered due to its position in your basic set +1, because you need an empty Element, which is then zero. Then of course first create a Set of Sets, that you are going to return as your powerset. After that cycle through your array of Integers as follows: Create a Set out of the current Integer-Array by parsing every Integer to its corresponding element of the Set. Then add one to the first Integer of your Integer-Array. If the number is then greater than the length of your basic Set, add one to the next Integer of your Array, setting the "overflowing" Integer equal to the next Integer in the Array +1.

This should allow you to cycle through every possible combination for the powerset and add them to the Set.

public Set&lt;Set&lt;T&gt;&gt; powerSet(){
    int[] num = new int[list.size()];
    Arrays.fill(num,0);
    Set&lt;Set&lt;T&gt;&gt; powerSet = new Set&lt;&gt;();
    do{
        powerSet.list.add(parse(num));
    }while (addNum(num)); //Loops through every possibility 
    powerSet.list.add(parse(num)); 
    //Because the method returns false when this was the last possible increment
    return powerSet;
}

//Transforms a int[] into the corresponding Set
private Set&lt;T&gt; parse(int[] e){
    Set&lt;T&gt; s = new Set&lt;&gt;();
    for (int i = 0; i &lt; e.length; i++) {
        if(e[i]!=0){
            s.list.add(list.get(e[i]-1)); //Every Element has its number
        }
    }
    return s;
}

//Increments the counter
//Returns false if this was the last possible increment
private boolean addNum(int[] e){
    e[0]++;
    for (int i = 0; i &lt; e.length; i++) {
        if(e[i]&gt;e.length-i){
            e[i] = 0;
            e[i+1]++;
        }
    }
    for (int i = e.length-1; i != 0; i--) {
        if(e[i]&gt;=e[i-1]&amp;&amp;e[i]!=0){
            e[i-1] = e[i]+1;
        }
    }
    if(e[e.length-1]==1){
        return false;
    }
    return true;
}

Output for [3,43,65,32] (printed out every Set of the powerset):

[]
[3]
[43]
[65]
[32]
[43, 3]
[65, 3]
[32, 3]
[65, 43]
[32, 43]
[32, 65]
[65, 43, 3]
[32, 43, 3]
[32, 65, 3]
[32, 65, 43]
[32, 65, 43, 3]

Although this may not be the most elegant way of solving the problem, it appears to work. I also don't know the requirements of the question. So maybe this answer isn't even suitable.

huangapple
  • 本文由 发表于 2020年3月15日 19:04:24
  • 转载请务必保留本文链接:https://java.coder-hub.com/60692185.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定