algorithm – 以非传统方式反转队列

假设我有一个填充了某种类型元素的队列,并且它们以这样的方式填充:如果任何两个元素被指定的比较器评估为相同,则它们将彼此相邻.

现在我想以下列方式反转队列:如果队列中的所有元素都是唯一的,那么将其反转为反向的正常定义.

如果有一些元素是相同的(并且它们将如何填充它们将彼此相邻),则反转队列但保持非唯一元素的相对位置不变.

图表可能更容易理解问题所在.

如果队列如下:

[11 22 33 44 55]

我的比较器通过查看它们的第一个数字来比较两个整数,然后上面队列的反向将是:

[55 44 33 22 11]

但是,如果我的输入队列是:

[11 22 23 44 55]

相反的应该是:

[55 44 22 23 11]

鉴于比较者.

我试图以递归方式执行此操作,只有一个堆栈作为附加辅助存储.但是,我很难找到正确有效的方法.能否请你帮忙?非常感谢你!

PS:我使用堆栈作为额外存储的原因是因为以传统方式反转队列最容易使用堆栈(出队并将全部推入堆栈,然后弹出并入队回队列).

最佳答案 方法1)

首先反转整个队列(不考虑21,22等的相等),然后使用堆栈反转每个单独的块(即21,22等).这可以迭代完成.

这类似于句子问题中的反向词(着名的访谈问题).

(参见下面的编写示例和伪代码)

方法2)

如果你想绝对做递归,那么我建议你使用Queue作为辅助存储,而不是堆栈.

您将一个块插入到辅助队列中,递归地反转列表的其余部分,然后将元素重新排入主队列.

代码将是这样的(handwavy pseudo)

StrangeReverse(Queue <T> q) {
    Queue<T> aux;
    // this removes first block from q, and places them in aux
    while (elem_of_first_block(q)) {
        aux.Enque(elem);
    }
    // Recursively reverse the rest of the q.
    StrangeReverse(q);

    // place the first block back in q, at the end.
    // in the order they appeared originally.
    while (aux.HasElements()) {
        q.Enque(aux.Deque());
    }
}

通过拥有一堆队列,可以将递归版本转换为迭代版本!您可以从每个块中创建一个队列,并将它们堆叠起来.然后弹出堆栈,使用队列.

方法1的一个成功案例

[11,12,21,22,43,44]

反转这个(使用堆栈或递归方法)

[44,43,22,21,12,11]

现在反转每个块:

推44,43.

Stack = [44,49].队列= [22,21,12,11]

现在Enque从堆栈中弹出

Stack = [],Queue = [22,21,12,11,43,44]

推22,21

Stack = [22,21],Queue = [12,11,43,44]

通过弹出堆栈来获得Enque.

Stack = [],Queue = [12,11,43,44,21,22]

最后我们得到了

[43,44,21,22,11,12]

注意:要确定块,您可能需要在队列上使用peek方法.

方法1的伪代码

void StrangeReverse(Queue<T> q) {
    Stack<T> s;
    int count = q.Count();
    if (count < 2) return;
    for (i = 0; i < count; i++) {
        T elem = q.Deque();
        s.Push(elem);
    }    
    while (s.HasElements()) {
        T elem = s.Pop();
        q.Enque(elem);
    }
    // Now the queue has been reversed,
    // in the normal fashion.
    ReverseBlocks(q);
}

void ReverseBlocks(Queue<T> q) {
    int reversed = 0;
    int count = q.Count();
    while (reversed < count) {
        reversed += ReverseSingleBlock(q);
    }
}

int ReverseSingleBlock(Queue <T> q) {
    Stack <T> s;
    T prevElem = q.Deque();
    s.Push(prevElem);
    T curElem = q.Peek();
    while(curElem == prevElem) {
        s.Push(curElem);
        q.Deque();
        prevElem = curElem;
        curElem = q.Peek();
    }
    int count = 0;
    while(s.HasElements()) {
        T elem = s.Pop();
        q.Enque(elem);
        count++;
    }
    return count;
}
点赞