【问题标题】:Getting a powerset recursively递归获取powerset
【发布时间】:2013-11-12 08:21:40
【问题描述】:

我想先说这是一个学校作业,所以当我需要帮助时,最好为我指出正确的方向,而不是给我代码来使用。

所以任务是能够打印出任何给定集合的 PowerSet(给定集合的所有子集的集合)。我对 Java 有一定的经验,但递归是我的弱点之一,所以我无法想象这一点。

我的方法返回所有包含“d”和空集的子集。

这是我目前所拥有的:

public static TreeSet<TreeSet<Character>> powerSet(TreeSet<Character> setIn) 
{
    Comparator<TreeSet<Character>> comp = new Comparator<TreeSet<Character>>() 
    {
        @Override
        public int compare(TreeSet<Character> a, TreeSet<Character> b)
        {
            return a.size() - b.size();
        }

    };          
    TreeSet<TreeSet<Character>> temp = new TreeSet<TreeSet<Character>>(comp);                                                                               

    if (setIn.isEmpty()) 
    {
        temp.add(new TreeSet<Character>());
        return temp;
    }

    Character first = setIn.first();
    msg(first);
    setIn.remove(first);
    TreeSet<TreeSet<Character>> setA = powerSet(setIn);
    temp.addAll(setA);  
    for (TreeSet<Character> prox : setA) 
    {
        TreeSet<Character> setB = new TreeSet<Character>(prox);
        setB.add(first);
        temp.add(setB); 
    }
    return temp;
}

给定集合

[a, b, c, d]

这个方法给了我一套

[[], [d], [c, d], [b, c, d], [a, b, c, d]]

但我们知道 PowerSet 应该是

[[], [a], [b], [c], [d], [a, b], [a, c], [a, d], [b, c], [b, d], [c, d],
 [a, b, c], [a, b, d], [a, c, d], [b, c, d], [a, b, c, d]]

我们将不胜感激任何朝着正确方向前进的帮助。

编辑:我的问题是一个非常愚蠢的问题。我忘记正确设置比较器,它排除了结果。我修复了比较器以正确排序而不会丢弃集合。

这里是:

  public int compare(TreeSet<Character> a, TreeSet<Character> b)
            {           
                if(a.equals(b))
                    return 0;

                if(a.size() > b.size())
                    return 1;

                return -1;
            }

【问题讨论】:

    标签: java recursion set powerset


    【解决方案1】:

    广泛的编辑:

    解决方案比我最初想象的要简单得多。除了以下几点之外,您所做的一切都很好:在从集合中删除第一个元素之前,将该集合添加到 temp 集合中。

    类似这样的:

     temp.add(setIn);
     Character first = setIn.first();
     msg(first);
     setIn.remove(first);
    

    【讨论】:

    • 但是如果你看看这里给出的算法en.wikipedia.org/wiki/Power_set#Algorithms,你只需要删除任何一个特定元素(这里是第一个),然后递归地找到剩余集合的幂集。
    • 我一直在努力实现这一点,但无论出于何种原因,我都无法想象如何做到这一点。我尝试使用循环(可能是一个糟糕的想法)都以堆栈溢出告终。 Character first = setIn.first(); TreeSet&lt;TreeSet&lt;Character&gt;&gt; setA = null; for(int x = 0; x &lt; setIn.size() - 1; x++) { setA = powerSet(setIn); setA.remove(first); }
    • 它以堆栈溢出结束,因为停止条件(即集合为空)从未满足;您正在使用作为参数传递给当前方法执行的同一组 (setIn) 递归调用该方法。您只能在递归调用之后从该数组中删除一个元素。不幸的是,该行永远不会到达,因为递归调用最终导致堆栈溢出。
    • @slider 那里的算法说你必须这样做的方式是将删除的元素与通过从初始集中删除该元素获得的集合的所有子集组合。这是正确的,它比我提出的方法更好。 (我的变体会导致重复的子集)
    • @Caboose 我误解了你的问题。我用改进的(阅读完全不同的)解决方案编辑了我的答案。
    【解决方案2】:

    目前看起来不错。

    您正在构建包含第一个元素的每个可能的子集 这可以非常简单地扩展为对初始集合的每个元素执行相同的操作。只需要做你已经在做的事情,但是对于初始集合的不同元素。

    这应该会让你更接近 powerset。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-06
      • 2022-01-24
      • 1970-01-01
      • 2014-04-10
      • 1970-01-01
      • 2018-10-07
      • 2011-11-26
      • 2014-04-17
      相关资源
      最近更新 更多