1

这是来自 Michael T Goodrich 和 Robert Tamassia 的 Java 数据结构和算法的问题。这个怎么做?任何帮助表示赞赏。

这就是我的想法,如果我错了,请纠正我:

将元素存储在堆栈中。弹出第一个元素并将其存储在队列中,堆栈中的剩余元素形成一个子集。恢复堆栈,现在弹出第二个元素(队列中的第一个弹出,队列中的第二个弹出,然后从队列中推送)和堆栈中的剩余元素从另一个子集中。同样弹出第三个元素,然后弹出第四个。现在,轮到对两个元素和三个元素做同样的事情了吗?我是否误解了这个问题并将其延伸得太远?

4

3 回答 3

2

我已经定义了 ArrayStack() 和 ArrayQueue() 类

n=[1,2,3,4,5]
st=ArrayStack()
q=ArrayQueue()

q.enqueue(set())

for i in range(len(n)):
    st.push(n[i])


while st.is_empty()==False:
    cur_el=st.pop()
    print('cur',cur_el)
    for i in range(len(q)):
        a=q.dequeue()
        print('a',a)
        q.enqueue(a)
        b=a|{cur_el}
        q.enqueue(b)
        print('b',b)

while q.isempty()==False:
    x=q.dequeue()
    print(x)

OUTPUT
cur 5
a set()
b {5}
cur 4
a set()
b {4}
a {5}
b {4, 5}
cur 3
a set()
b {3}
a {4}
b {3, 4}
a {5}
b {3, 5}
a {4, 5}
b {3, 4, 5}
cur 2
a set()
b {2}
a {3}
b {2, 3}
a {4}
b {2, 4}
a {3, 4}
b {2, 3, 4}
a {5}
b {2, 5}
a {3, 5}
b {2, 3, 5}
a {4, 5}
b {2, 4, 5}
a {3, 4, 5}
b {2, 3, 4, 5}
cur 1
a set()
b {1}
a {2}
b {1, 2}
a {3}
b {1, 3}
a {2, 3}
b {1, 2, 3}
a {4}
b {1, 4}
a {2, 4}
b {1, 2, 4}
a {3, 4}
b {1, 3, 4}
a {2, 3, 4}
b {1, 2, 3, 4}
a {5}
b {1, 5}
a {2, 5}
b {1, 2, 5}
a {3, 5}
b {1, 3, 5}
a {2, 3, 5}
b {1, 2, 3, 5}
a {4, 5}
b {1, 4, 5}
a {2, 4, 5}
b {1, 2, 4, 5}
a {3, 4, 5}
b {1, 3, 4, 5}
a {2, 3, 4, 5}
b {1, 2, 3, 4, 5}
set()
{1}
{2}
{1, 2}
{3}
{1, 3}
{2, 3}
{1, 2, 3}
{4}
{1, 4}
{2, 4}
{1, 2, 4}
{3, 4}
{1, 3, 4}
{2, 3, 4}
{1, 2, 3, 4}
{5}
{1, 5}
{2, 5}
{1, 2, 5}
{3, 5}
{1, 3, 5}
{2, 3, 5}
{1, 2, 3, 5}
{4, 5}
{1, 4, 5}
{2, 4, 5}
{1, 2, 4, 5}
{3, 4, 5}
{1, 3, 4, 5}
{2, 3, 4, 5}
{1, 2, 3, 4, 5}
于 2018-09-17T06:27:11.690 回答
0

只是半开玩笑:

  1. 创建堆栈并忽略它;
  2. 创建队列并忽略它;
  3. 以长度为 N 的二进制形式输出(迭代地)从 0 到 (2^N)-1 的数字,前导零。

通过将每个 1 位解释为包含,将每个 0 位解释为排除,可以很容易地从生成的整数的二进制表示中生成任何所需的子集替代表示。

从技术上讲,这符合标准,因为它 (a) 创建了一个堆栈;(b) 创建队列;(c) 非递归地生成 N 个元素集的所有可能子集。对于迭代解决方案,堆栈和队列是严格冗余的,所以为什么在没有任何进一步指导/约束的情况下要求它们。

更新:

对输入集的随机访问可以通过使用队列来代替,将其视为循环缓冲区。(当然,它不能用于其他任何事情。)可以将标记元素添加到队列中以指示每个循环何时完成,但对于上述算法来说更自然的是一次处理 N 个元素, N 是预先知道的。当每个元素出队时,它会被处理(为当前子集添加或忽略)并再次入队。

于 2013-04-12T05:41:39.907 回答
0

我想我有一个从这里被盗的合理解决方案:http ://arstechnica.com/civis/viewtopic.php?f=20&t=96354&sid=e74a29103e9297050680afbba6b72f32&start=40

所以这个想法是队列将保存子集,而您的堆栈将保存您的原始集合。空集是每个集的子集,因此我们用它初始化队列。然后,对于堆栈上的每个元素,我们将其弹出。现在对于队列中的每个子集,我们将该子集出列并入列两个副本:1)一个没有新元素(即与原始元素相同),2)一个有新元素。棘手的部分是跟踪何时需要弹出堆栈的下一个元素(即,当您完成当前元素时)。一种方法是检查整个 Queue 是否有匹配集(这意味着您已经添加了您构建的这个子集......所以停止)。但是一种更好/更清洁的方法是使用空集作为标记。

基本上你有典型的递归解决方案:

GenerateSubsets(Set set)
{
    if (set == Set.EmptySet)
        return new List<Set>(set);

    var elem = set.Remove();
    var subsets = GenerateSubsets(set);
    // Add all of thew subsets that contain elem (i.e. partition all subsets
    // by whether they contain elem or do not contain elem)
    subsets.AddRange(subsets.Map(subset => subset.Add(elem));

    return subsets;
}

我们使用完全相同的想法,其中 Queue迭代构造subsets,原始集合存储在 Stack 中。

GenerateSubsets(Stack originalSetAsStack)
{
    var queue = new Queue { new Set() };
    while (!originalSetAsStack.IsEmpty)
    {
        var elem = originalSetAsStack.Pop();
        while (true)
        {
            var currSubset = queue.Dequeue();
            // This is key. This is how we know when to start
            // the next iteration!
            // This also assumes that any two empty sets are equal...
            if (currSubset == new Set())
            {
                break;
            }

            var subsetWithElem = currSubset.Clone();
            subsetWithElem.Add(elem);
            // Add back in current subset. This has to be first!
            // for our break to work above
            queue.Queue(currSubset);
            queue.Queue(subsetWithElem);
        }
    }

    return queue;
}

说明为什么这个解决方案源于递归解决方案。观察:我们迭代地构造子集:

-Start with the empty set => ({})
-Take some element from the stack
-Now for each element in the Queue, enqueue two: one with the current
element, and one without => ({}, {elem})
-Now take the next element and do the same => ({}, {elem}, {nextElem}, 
{elem, NextElem})
-Now take the third element and do the same => ({}, {elem}, {nextElem}, 
{elem, nextElem}, {thirdElem}, {thirdElem, elem}, {thirdElem, nextElem}, 
{elem, nextElem, thirdElem})
-...
于 2013-04-12T08:48:21.657 回答